diff --git a/engines/sci/engine/kmenu.cpp b/engines/sci/engine/kmenu.cpp index 94cc4b17496..b0af2843058 100644 --- a/engines/sci/engine/kmenu.cpp +++ b/engines/sci/engine/kmenu.cpp @@ -47,7 +47,18 @@ reg_t kAddMenu(EngineState *s, int argc, reg_t *argv) { reg_t kSetMenu(EngineState *s, int argc, reg_t *argv) { - s->_gui->menuSet(argc, argv); + uint16 menuId = argv[0].toUint16() >> 8; + uint16 itemId = argv[0].toUint16() & 0xFF; + uint16 attributeId; + int argPos = 1; + + while (argPos < argc) { + attributeId = argv[argPos].toUint16(); + if ((argPos + 1) >= argc) + error("Too few parameters for kSetMenu"); + s->_gui->menuSet(menuId, itemId, attributeId, argv[argPos + 1]); + argPos += 2; + } return s->r_acc; } diff --git a/engines/sci/gui/gui.cpp b/engines/sci/gui/gui.cpp index e3b05c6cd0b..62dfbd0d89b 100644 --- a/engines/sci/gui/gui.cpp +++ b/engines/sci/gui/gui.cpp @@ -306,21 +306,24 @@ void SciGui::drawStatus(const char *text, int16 colorPen, int16 colorBack) { void SciGui::drawMenuBar(bool clear) { if (!clear) { - warning("TODO: drawMenuBar()"); + GuiPort *oldPort = _gfx->SetPort(_gfx->_menuPort); + _menu->drawBar(); + _gfx->SetPort(oldPort); } else { drawStatus("", 0, 0); } } void SciGui::menuAdd(Common::String title, Common::String content, reg_t entriesBase) { - warning("menuAdd"); + _menu->add(title, content); } -void SciGui::menuSet(int argc, reg_t *argv) { +void SciGui::menuSet(uint16 menuId, uint16 itemId, uint16 attributeId, reg_t value) { + _menu->setAttribute(menuId, itemId, attributeId, value); } reg_t SciGui::menuGet(uint16 menuId, uint16 itemId, uint16 attributeId) { - return NULL_REG; + return _menu->getAttribute(menuId, itemId, attributeId); } reg_t SciGui::menuSelect(reg_t eventObject) { diff --git a/engines/sci/gui/gui.h b/engines/sci/gui/gui.h index 9208562f254..cb3ff189a99 100644 --- a/engines/sci/gui/gui.h +++ b/engines/sci/gui/gui.h @@ -82,7 +82,7 @@ public: virtual void drawStatus(const char *text, int16 colorPen, int16 colorBack); virtual void drawMenuBar(bool clear); virtual void menuAdd(Common::String title, Common::String content, reg_t entriesBase); - virtual void menuSet(int argc, reg_t *argv); + virtual void menuSet(uint16 menuId, uint16 itemId, uint16 attributeId, reg_t value); virtual reg_t menuGet(uint16 menuId, uint16 itemId, uint16 attributeId); virtual reg_t menuSelect(reg_t eventObject); diff --git a/engines/sci/gui/gui_menu.cpp b/engines/sci/gui/gui_menu.cpp index 89a5fefa9ce..737e90f35ec 100644 --- a/engines/sci/gui/gui_menu.cpp +++ b/engines/sci/gui/gui_menu.cpp @@ -39,13 +39,181 @@ namespace Sci { SciGuiMenu::SciGuiMenu(SciGuiGfx *gfx, SciGuiText *text, SciGuiScreen *screen) : _gfx(gfx), _text(text), _screen(screen) { - init(); } SciGuiMenu::~SciGuiMenu() { } -void SciGuiMenu::init() { +void SciGuiMenu::add(Common::String title, Common::String content) { + GuiMenuEntry *menuEntry; + uint16 itemCount = 0; + GuiMenuItemEntry *itemEntry; + int contentSize = content.size(); + int separatorCount; + int curPos, beginPos, endPos, tempPos; + int tagPos, rightAlignedPos, functionPos, altPos, controlPos; + + // Sierra SCI starts with id 1, so we do so as well + _listCount++; + menuEntry = new GuiMenuEntry(_listCount); + menuEntry->text = title; + _list.push_back(menuEntry); + + curPos = 0; + do { + itemCount++; + itemEntry = new GuiMenuItemEntry(_listCount, itemCount); + + beginPos = curPos; + + // Now go through the content till we find end-marker and collect data about it + // ':' is an end-marker for each item + tagPos = 0; rightAlignedPos = 0; + controlPos = 0; altPos = 0; functionPos = 0; + while ((curPos < contentSize) && (content[curPos] != ':')) { + switch (content[curPos]) { + case '=': // Set tag + if (tagPos) + error("multiple tag markers within one menu-item"); + tagPos = curPos; + break; + case '`': // Right-aligned + if (rightAlignedPos) + error("multiple right-aligned markers within one menu-item"); + rightAlignedPos = curPos; + break; + case '^': // Ctrl-prefix + if (controlPos) + error("multiple control markers within one menu-item"); + controlPos = curPos; + break; + case '@': // Alt-prefix + if (altPos) + error("multiple alt markers within one menu-item"); + altPos = curPos; + break; + case '#': // Function-prefix + if (functionPos) + error("multiple function markers within one menu-item"); + functionPos = curPos; + break; + } + curPos++; + } + endPos = curPos; + + // Control/Alt/Function key mapping... + if (controlPos) { + content.setChar(SCI_MENU_REPLACE_ONCONTROL, controlPos); + itemEntry->keyModifier = SCI_EVM_CTRL; + tempPos = controlPos + 1; + if (tempPos >= contentSize) + error("control marker at end of item"); + itemEntry->keyPress = tolower(content[tempPos]); + content.setChar(toupper(content[tempPos]), tempPos); + } + if (altPos) { + content.setChar(SCI_MENU_REPLACE_ONALT, altPos); + itemEntry->keyModifier = SCI_EVM_ALT; + tempPos = altPos + 1; + if (tempPos >= contentSize) + error("alt marker at end of item"); + itemEntry->keyPress = tolower(content[tempPos]); + content.setChar(toupper(content[tempPos]), tempPos); + } + if (functionPos) { + content.setChar(SCI_MENU_REPLACE_ONFUNCTION, functionPos); + tempPos = functionPos + 1; + if (tempPos >= contentSize) + error("function marker at end of item"); + itemEntry->keyPress = content[tempPos]; + switch (content[functionPos + 1]) { + case '1': itemEntry->keyPress = SCI_K_F1; break; + case '2': itemEntry->keyPress = SCI_K_F2; break; + case '3': itemEntry->keyPress = SCI_K_F3; break; + case '4': itemEntry->keyPress = SCI_K_F4; break; + case '5': itemEntry->keyPress = SCI_K_F5; break; + case '6': itemEntry->keyPress = SCI_K_F6; break; + case '7': itemEntry->keyPress = SCI_K_F7; break; + case '8': itemEntry->keyPress = SCI_K_F8; break; + case '9': itemEntry->keyPress = SCI_K_F9; break; + case '0': itemEntry->keyPress = SCI_K_F10; break; + default: + error("illegal function key specified"); + } + } + + // Now get all strings + tempPos = endPos; + if (rightAlignedPos) { + tempPos = rightAlignedPos; + } else if (tagPos) { + tempPos = tagPos; + } + curPos = beginPos; + separatorCount = 0; + while (curPos < tempPos) { + switch (content[curPos]) { + case '!': + case '-': + case ' ': + separatorCount++; + } + curPos++; + } + if (separatorCount == tempPos - beginPos) { + itemEntry->separatorLine = true; + } else { + itemEntry->text = Common::String(content.c_str() + beginPos, tempPos - beginPos); + } + + if (rightAlignedPos) { + rightAlignedPos++; + tempPos = endPos; + if (tagPos) + tempPos = tagPos; + itemEntry->textRightAligned = Common::String(content.c_str() + rightAlignedPos, tempPos - rightAlignedPos); + } + + if (tagPos) { + tempPos = functionPos + 1; + if (tempPos >= contentSize) + error("tag marker at end of item"); + itemEntry->tag = atoi(content.c_str() + tempPos); + } + + curPos = endPos + 1; + + _itemList.push_back(itemEntry); + } while (curPos < contentSize); +} + +void SciGuiMenu::setAttribute(uint16 menuId, uint16 itemId, uint16 attributeId, reg_t value) { + warning("setAttr: %d %d %d", menuId, itemId, attributeId); +} + +reg_t SciGuiMenu::getAttribute(uint16 menuId, uint16 itemId, uint16 attributeId) { + return NULL_REG; +} + +void SciGuiMenu::drawBar() { + GuiMenuEntry *listEntry; + GuiMenuList::iterator listIterator; + GuiMenuList::iterator listEnd = _list.end(); + + // Hardcoded black on white + _gfx->FillRect(_gfx->_menuRect, 1, _screen->_colorWhite); + _gfx->PenColor(0); + _gfx->MoveTo(8, 1); + + listIterator = _list.begin(); + while (listIterator != listEnd) { + listEntry = *listIterator; + _text->Draw_String(listEntry->text.c_str()); + + listIterator++; + } + _gfx->BitsShow(_gfx->_menuRect); } } // End of namespace Sci diff --git a/engines/sci/gui/gui_menu.h b/engines/sci/gui/gui_menu.h index d3119f20841..919cc39dca5 100644 --- a/engines/sci/gui/gui_menu.h +++ b/engines/sci/gui/gui_menu.h @@ -28,18 +28,67 @@ namespace Sci { +enum { + SCI_MENU_ATTRIBUTE_SAID = 0x6d, + SCI_MENU_ATTRIBUTE_TEXT = 0x6e, + SCI_MENU_ATTRIBUTE_KEY = 0x6f, + SCI_MENU_ATTRIBUTE_ENABLED = 0x70, + SCI_MENU_ATTRIBUTE_TAG = 0x71 +}; + +enum { + SCI_MENU_REPLACE_ONCONTROL = 0x03, + SCI_MENU_REPLACE_ONALT = 0x02, + SCI_MENU_REPLACE_ONFUNCTION = 'F' +}; + +struct GuiMenuEntry { + uint16 id; + Common::String text; + + GuiMenuEntry(uint16 id) + : id(id) { } +}; +typedef Common::List GuiMenuList; + +struct GuiMenuItemEntry { + uint16 menuId; + uint16 id; + bool enabled; + uint16 tag; + uint16 keyPress; + uint16 keyModifier; + bool separatorLine; + Common::String said; + Common::String text; + Common::String textRightAligned; + + GuiMenuItemEntry(uint16 menuId, uint16 id) + : menuId(menuId), id(id), + enabled(true), tag(0), keyPress(0), keyModifier(0), separatorLine(false) { } +}; +typedef Common::List GuiMenuItemList; + class SciGuiMenu { public: SciGuiMenu(SciGuiGfx *gfx, SciGuiText *text, SciGuiScreen *screen); ~SciGuiMenu(); + void add(Common::String title, Common::String content); + void setAttribute(uint16 menuId, uint16 itemId, uint16 attributeId, reg_t value); + reg_t getAttribute(uint16 menuId, uint16 itemId, uint16 attributeId); + + void drawBar(); private: - void init(void); SciGuiGfx *_gfx; SciGuiText *_text; SciGuiScreen *_screen; + + uint16 _listCount; + GuiMenuList _list; + GuiMenuItemList _itemList; }; } // End of namespace Sci diff --git a/engines/sci/gui32/gui32.cpp b/engines/sci/gui32/gui32.cpp index 3a51f92aa90..5b6900f6ebe 100644 --- a/engines/sci/gui32/gui32.cpp +++ b/engines/sci/gui32/gui32.cpp @@ -834,14 +834,8 @@ void SciGui32::menuAdd(Common::String title, Common::String content, reg_t entri _s->_menubar->addMenu(_s->gfx_state, title, content, titlebarFont, entriesBase); } -void SciGui32::menuSet(int argc, reg_t *argv) { - int index = argv[0].toUint16(); - int i = 2; - - while (i < argc) { - _s->_menubar->setAttribute(_s, (index >> 8) - 1, (index & 0xff) - 1, argv[i - 1].toUint16(), argv[i]); - i += 2; - } +void SciGui32::menuSet(uint16 menuId, uint16 itemId, uint16 attributeId, reg_t value) { + _s->_menubar->setAttribute(_s, menuId - 1, itemId - 1, attributeId, value); } reg_t SciGui32::menuGet(uint16 menuId, uint16 itemId, uint16 attributeId) { diff --git a/engines/sci/gui32/gui32.h b/engines/sci/gui32/gui32.h index 6256ee15ff1..a0dae12f0e1 100644 --- a/engines/sci/gui32/gui32.h +++ b/engines/sci/gui32/gui32.h @@ -61,7 +61,7 @@ public: void drawStatus(const char *text, int16 colorPen, int16 colorBack); void drawMenuBar(bool clear); void menuAdd(Common::String title, Common::String content, reg_t entriesBase); - void menuSet(int argc, reg_t *argv); + void menuSet(uint16 menuId, uint16 itemId, uint16 attributeId, reg_t value); reg_t menuGet(uint16 menuId, uint16 itemId, uint16 attributeId); reg_t menuSelect(reg_t eventObject);