diff options
author | simonb <simonb> | 2006-06-25 09:05:58 (GMT) |
---|---|---|
committer | simonb <simonb> | 2006-06-25 09:05:58 (GMT) |
commit | 80389b5dd5e7be4025cafbb2e7b055fd06f4f56d (patch) | |
tree | 1406d6c5044958bc40f2b7f4f8326ca8cc01629f /src/MenuCreator.cc | |
parent | 577859034db0e0e36ceab85ebba62e1018dd3361 (diff) | |
download | fluxbox-80389b5dd5e7be4025cafbb2e7b055fd06f4f56d.zip fluxbox-80389b5dd5e7be4025cafbb2e7b055fd06f4f56d.tar.bz2 |
support encodings in menu files
Diffstat (limited to 'src/MenuCreator.cc')
-rw-r--r-- | src/MenuCreator.cc | 132 |
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> |
56 | using namespace std; | 56 | using namespace std; |
57 | 57 | ||
58 | std::list<std::string> MenuCreator::encoding_stack; | ||
59 | std::list<size_t> MenuCreator::stacksize_stack; | ||
60 | |||
61 | FbTk::StringConvertor MenuCreator::m_stringconvertor(FbTk::StringConvertor::ToFbString); | ||
62 | |||
58 | static void createStyleMenu(FbTk::Menu &parent, const std::string &label, | 63 | static 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 { | |||
131 | public: | 136 | public: |
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 | ||
161 | static void translateMenuItem(Parser &parse, ParseItem &item); | 167 | static void translateMenuItem(Parser &parse, ParseItem &item, FbTk::StringConvertor &labelconvertor); |
162 | 168 | ||
163 | 169 | ||
164 | static void parseMenu(Parser &pars, FbTk::Menu &menu) { | 170 | static 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 | ||
174 | static void translateMenuItem(Parser &parse, ParseItem &pitem) { | 180 | static 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 | ||
340 | static void parseWindowMenu(Parser &parse, FbTk::Menu &menu) { | 348 | static 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 | ||
376 | bool getStart(FbMenuParser &parser, std::string &label) { | 384 | bool 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 | ||
392 | FbTk::Menu *MenuCreator::createFromFile(const std::string &filename, int screen_number, bool require_begin) { | 400 | FbTk::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 */ | ||
602 | void 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 | */ | ||
612 | void 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 | */ | ||
633 | void 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 | */ | ||
646 | void 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 | |||