diff options
author | Marek Sokolowski <mnbvmar@gmail.com> | 2017-09-29 22:25:05 +0000 |
---|---|---|
committer | Marek Sokolowski <mnbvmar@gmail.com> | 2017-09-29 22:25:05 +0000 |
commit | ea529937cede4029b2145fdccd82f22dd3b0c24a (patch) | |
tree | 4977a27ac655efd0cfcc68cc55839b5454fa93cf /tools/llvm-rc | |
parent | 9e5998cdf769181e4977d0a8e9e535c55ca1de7c (diff) |
[llvm-rc] Serialize MENU resources to .res files (serialization, pt 3).
This allows MENU resources to be serialized.
MENU resource statement doc:
msdn.microsoft.com/en-us/library/windows/desktop/aa381025.aspx
POPUP sub-statement doc:
msdn.microsoft.com/en-us/library/windows/desktop/aa381030.aspx
MENUITEM sub-statement doc:
msdn.microsoft.com/en-us/library/windows/desktop/aa381024.aspx
MENUHEADER structure:
msdn.microsoft.com/en-us/library/windows/desktop/ms648018.aspx (and
NORMALMENUITEM, POPUPMENUITEM structs).
Thanks for Nico Weber for his original work in this area.
Differential Revision: https://reviews.llvm.org/D37828
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@314562 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/llvm-rc')
-rw-r--r-- | tools/llvm-rc/ResourceFileWriter.cpp | 54 | ||||
-rw-r--r-- | tools/llvm-rc/ResourceFileWriter.h | 7 | ||||
-rw-r--r-- | tools/llvm-rc/ResourceScriptStmt.h | 40 | ||||
-rw-r--r-- | tools/llvm-rc/ResourceVisitor.h | 1 |
4 files changed, 98 insertions, 4 deletions
diff --git a/tools/llvm-rc/ResourceFileWriter.cpp b/tools/llvm-rc/ResourceFileWriter.cpp index f8ba2a7694a..af002e347be 100644 --- a/tools/llvm-rc/ResourceFileWriter.cpp +++ b/tools/llvm-rc/ResourceFileWriter.cpp @@ -205,6 +205,10 @@ Error ResourceFileWriter::visitHTMLResource(const RCResource *Res) { return writeResource(Res, &ResourceFileWriter::writeHTMLBody); } +Error ResourceFileWriter::visitMenuResource(const RCResource *Res) { + return writeResource(Res, &ResourceFileWriter::writeMenuBody); +} + Error ResourceFileWriter::visitCharacteristicsStmt( const CharacteristicsStmt *Stmt) { ObjectData.Characteristics = Stmt->Value; @@ -382,5 +386,55 @@ Error ResourceFileWriter::writeHTMLBody(const RCResource *Base) { return appendFile(cast<HTMLResource>(Base)->HTMLLoc); } +// --- MenuResource helpers. --- // + +Error ResourceFileWriter::writeMenuDefinition( + const std::unique_ptr<MenuDefinition> &Def, uint16_t Flags) { + assert(Def); + const MenuDefinition *DefPtr = Def.get(); + + if (auto *MenuItemPtr = dyn_cast<MenuItem>(DefPtr)) { + writeInt<uint16_t>(Flags); + RETURN_IF_ERROR( + checkNumberFits<uint16_t>(MenuItemPtr->Id, "MENUITEM action ID")); + writeInt<uint16_t>(MenuItemPtr->Id); + RETURN_IF_ERROR(writeCString(MenuItemPtr->Name)); + return Error::success(); + } + + if (isa<MenuSeparator>(DefPtr)) { + writeInt<uint16_t>(Flags); + writeInt<uint32_t>(0); + return Error::success(); + } + + auto *PopupPtr = cast<PopupItem>(DefPtr); + writeInt<uint16_t>(Flags); + RETURN_IF_ERROR(writeCString(PopupPtr->Name)); + return writeMenuDefinitionList(PopupPtr->SubItems); +} + +Error ResourceFileWriter::writeMenuDefinitionList( + const MenuDefinitionList &List) { + for (auto &Def : List.Definitions) { + uint16_t Flags = Def->getResFlags(); + // Last element receives an additional 0x80 flag. + const uint16_t LastElementFlag = 0x0080; + if (&Def == &List.Definitions.back()) + Flags |= LastElementFlag; + + RETURN_IF_ERROR(writeMenuDefinition(Def, Flags)); + } + return Error::success(); +} + +Error ResourceFileWriter::writeMenuBody(const RCResource *Base) { + // At first, MENUHEADER structure. In fact, these are two WORDs equal to 0. + // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648018.aspx + writeObject<uint32_t>(0); + + return writeMenuDefinitionList(cast<MenuResource>(Base)->Elements); +} + } // namespace rc } // namespace llvm diff --git a/tools/llvm-rc/ResourceFileWriter.h b/tools/llvm-rc/ResourceFileWriter.h index ce730d20eed..ef736baa169 100644 --- a/tools/llvm-rc/ResourceFileWriter.h +++ b/tools/llvm-rc/ResourceFileWriter.h @@ -32,6 +32,7 @@ public: Error visitNullResource(const RCResource *) override; Error visitAcceleratorsResource(const RCResource *) override; Error visitHTMLResource(const RCResource *) override; + Error visitMenuResource(const RCResource *) override; Error visitCharacteristicsStmt(const CharacteristicsStmt *) override; Error visitLanguageStmt(const LanguageResource *) override; @@ -63,6 +64,12 @@ private: // HTMLResource Error writeHTMLBody(const RCResource *); + // MenuResource + Error writeMenuDefinition(const std::unique_ptr<MenuDefinition> &, + uint16_t Flags); + Error writeMenuDefinitionList(const MenuDefinitionList &List); + Error writeMenuBody(const RCResource *); + // Output stream handling. std::unique_ptr<raw_fd_ostream> FS; diff --git a/tools/llvm-rc/ResourceScriptStmt.h b/tools/llvm-rc/ResourceScriptStmt.h index 6f83d722d24..d00e178426d 100644 --- a/tools/llvm-rc/ResourceScriptStmt.h +++ b/tools/llvm-rc/ResourceScriptStmt.h @@ -315,6 +315,8 @@ public: MENUBREAK = 0x0040 }; + enum MenuDefKind { MkBase, MkSeparator, MkMenuItem, MkPopup }; + static constexpr size_t NumFlags = 6; static StringRef OptionsStr[NumFlags]; static uint32_t OptionsFlags[NumFlags]; @@ -323,13 +325,16 @@ public: return OS << "Base menu definition\n"; } virtual ~MenuDefinition() {} + + virtual uint16_t getResFlags() const { return 0; } + virtual MenuDefKind getKind() const { return MkBase; } }; // Recursive description of a whole submenu. class MenuDefinitionList : public MenuDefinition { +public: std::vector<std::unique_ptr<MenuDefinition>> Definitions; -public: void addDefinition(std::unique_ptr<MenuDefinition> Def) { Definitions.push_back(std::move(Def)); } @@ -342,46 +347,73 @@ public: class MenuSeparator : public MenuDefinition { public: raw_ostream &log(raw_ostream &) const override; + + MenuDefKind getKind() const override { return MkSeparator; } + static bool classof(const MenuDefinition *D) { + return D->getKind() == MkSeparator; + } }; // MENUITEM statement definition. // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381024(v=vs.85).aspx class MenuItem : public MenuDefinition { +public: StringRef Name; uint32_t Id; uint16_t Flags; -public: MenuItem(StringRef Caption, uint32_t ItemId, uint16_t ItemFlags) : Name(Caption), Id(ItemId), Flags(ItemFlags) {} raw_ostream &log(raw_ostream &) const override; + + uint16_t getResFlags() const override { return Flags; } + MenuDefKind getKind() const override { return MkMenuItem; } + static bool classof(const MenuDefinition *D) { + return D->getKind() == MkMenuItem; + } }; // POPUP statement definition. // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381030(v=vs.85).aspx class PopupItem : public MenuDefinition { +public: StringRef Name; uint16_t Flags; MenuDefinitionList SubItems; -public: PopupItem(StringRef Caption, uint16_t ItemFlags, MenuDefinitionList &&SubItemsList) : Name(Caption), Flags(ItemFlags), SubItems(std::move(SubItemsList)) {} raw_ostream &log(raw_ostream &) const override; + + // This has an additional (0x10) flag. It doesn't match with documented + // 0x01 flag, though. + uint16_t getResFlags() const override { return Flags | 0x10; } + MenuDefKind getKind() const override { return MkPopup; } + static bool classof(const MenuDefinition *D) { + return D->getKind() == MkPopup; + } }; // Menu resource definition. class MenuResource : public OptStatementsRCResource { +public: MenuDefinitionList Elements; -public: MenuResource(OptionalStmtList &&OptStmts, MenuDefinitionList &&Items) : OptStatementsRCResource(std::move(OptStmts)), Elements(std::move(Items)) {} raw_ostream &log(raw_ostream &) const override; + + IntOrString getResourceType() const override { return RkMenu; } + Twine getResourceTypeName() const override { return "MENU"; } + Error visit(Visitor *V) const override { return V->visitMenuResource(this); } + ResourceKind getKind() const override { return RkMenu; } + static bool classof(const RCResource *Res) { + return Res->getKind() == RkMenu; + } }; // STRINGTABLE resource. Contains a list of strings, each having its unique ID. diff --git a/tools/llvm-rc/ResourceVisitor.h b/tools/llvm-rc/ResourceVisitor.h index 358a31c875c..14992dac5af 100644 --- a/tools/llvm-rc/ResourceVisitor.h +++ b/tools/llvm-rc/ResourceVisitor.h @@ -30,6 +30,7 @@ public: virtual Error visitNullResource(const RCResource *) = 0; virtual Error visitAcceleratorsResource(const RCResource *) = 0; virtual Error visitHTMLResource(const RCResource *) = 0; + virtual Error visitMenuResource(const RCResource *) = 0; virtual Error visitCharacteristicsStmt(const CharacteristicsStmt *) = 0; virtual Error visitLanguageStmt(const LanguageResource *) = 0; |