[llvm-rc] Add DIALOG(EX) parsing ability (parser, pt 5/8).
This extends the set of resources parsed by llvm-rc by DIALOG and DIALOGEX. Additionally, three optional resource statements specific to these two resources are added: CAPTION, FONT, and STYLE. Thanks for Nico Weber for his original work in this area. Differential Revision: https://reviews.llvm.org/D36905 llvm-svn: 312009
This commit is contained in:
parent
c6f6aa441b
commit
4ac54d9302
|
@ -56,3 +56,25 @@ LANGUAGE 4, 1
|
||||||
MENUITEM "&Word", 502
|
MENUITEM "&Word", 502
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14 DIALOGEX 50, 60, 10, 20, 500
|
||||||
|
LANGUAGE 1, 2
|
||||||
|
CHARACTERISTICS 50
|
||||||
|
VERSION 100
|
||||||
|
FONT 12, "Arial"
|
||||||
|
CAPTION "RC parser dialog"
|
||||||
|
STYLE 0x51234
|
||||||
|
BEGIN
|
||||||
|
LTEXT "Hello world!", 14, 20, 20, 50, 50
|
||||||
|
RTEXT "Heh", 50, 51, 52, 53, 54, 55, 56
|
||||||
|
CTEXT "Muuuu", 1, 2, 3, 4, 5, 6, 7, 8
|
||||||
|
PUSHBUTTON "Muuuu", 1, 2, 3, 4, 5, 6, 7, 8
|
||||||
|
DEFPUSHBUTTON "Muuuu", 1, 2, 3, 4, 5, 6
|
||||||
|
EDITTEXT 5, 1, 2, 4, 7, 8
|
||||||
|
END
|
||||||
|
|
||||||
|
25 DIALOG 1, 2, 3, 4
|
||||||
|
BEGIN
|
||||||
|
END
|
||||||
|
|
||||||
|
26 DIALOGEX 1, 2, 3, 4 {}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
3 DIALOG 1, 2, 3, 4, 500 {}
|
|
@ -0,0 +1,3 @@
|
||||||
|
1 DIALOG 1, 2, 3, 4 {
|
||||||
|
LTEXT "Too short", 1, 2, 3
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
1 DIALOGEX 1, 2, 3, 4 {
|
||||||
|
LTEXT "Too long", 1, 2, 3, 4, 5, 6, 7, 8, 9
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
1 DIALOGEX 1, 2, 3, 4 {
|
||||||
|
UNKNOWN 1, 2, 3, 4, 5, 6, 7, 8
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
1 DIALOGEX 1, 2, 3, 4 {
|
||||||
|
EDITTEXT "This shouldn't be here", 1, 2, 3, 4
|
||||||
|
}
|
|
@ -49,6 +49,21 @@
|
||||||
; PGOOD-NEXT: MenuItem ("&Word"), ID = 502
|
; PGOOD-NEXT: MenuItem ("&Word"), ID = 502
|
||||||
; PGOOD-NEXT: Menu list ends
|
; PGOOD-NEXT: Menu list ends
|
||||||
; PGOOD-NEXT: Menu list ends
|
; PGOOD-NEXT: Menu list ends
|
||||||
|
; PGOOD-NEXT: DialogEx (14): loc: (50, 60), size: [10, 20], help ID: 500
|
||||||
|
; PGOOD-NEXT: Option: Language: 1, Sublanguage: 2
|
||||||
|
; PGOOD-NEXT: Option: Characteristics: 50
|
||||||
|
; PGOOD-NEXT: Option: Version: 100
|
||||||
|
; PGOOD-NEXT: Option: Font: size = 12, face = "Arial"
|
||||||
|
; PGOOD-NEXT: Option: Caption: "RC parser dialog"
|
||||||
|
; PGOOD-NEXT: Option: Style: 332340
|
||||||
|
; PGOOD-NEXT: Control (14): LTEXT, title: "Hello world!", loc: (20, 20), size: [50, 50]
|
||||||
|
; PGOOD-NEXT: Control (50): RTEXT, title: "Heh", loc: (51, 52), size: [53, 54], style: 55, ext. style: 56
|
||||||
|
; PGOOD-NEXT: Control (1): CTEXT, title: "Muuuu", loc: (2, 3), size: [4, 5], style: 6, ext. style: 7, help ID: 8
|
||||||
|
; PGOOD-NEXT: Control (1): PUSHBUTTON, title: "Muuuu", loc: (2, 3), size: [4, 5], style: 6, ext. style: 7, help ID: 8
|
||||||
|
; PGOOD-NEXT: Control (1): DEFPUSHBUTTON, title: "Muuuu", loc: (2, 3), size: [4, 5], style: 6
|
||||||
|
; PGOOD-NEXT: Control (5): EDITTEXT, title: , loc: (1, 2), size: [4, 7], style: 8
|
||||||
|
; PGOOD-NEXT: Dialog (25): loc: (1, 2), size: [3, 4], help ID: 0
|
||||||
|
; PGOOD-NEXT: DialogEx (26): loc: (1, 2), size: [3, 4], help ID: 0
|
||||||
|
|
||||||
|
|
||||||
; RUN: not llvm-rc /V %p/Inputs/parser-stringtable-no-string.rc 2>&1 | FileCheck %s --check-prefix PSTRINGTABLE1
|
; RUN: not llvm-rc /V %p/Inputs/parser-stringtable-no-string.rc 2>&1 | FileCheck %s --check-prefix PSTRINGTABLE1
|
||||||
|
@ -144,3 +159,28 @@
|
||||||
; RUN: not llvm-rc /V %p/Inputs/parser-menu-misspelled-separator.rc 2>&1 | FileCheck %s --check-prefix PMENU4
|
; RUN: not llvm-rc /V %p/Inputs/parser-menu-misspelled-separator.rc 2>&1 | FileCheck %s --check-prefix PMENU4
|
||||||
|
|
||||||
; PMENU4: llvm-rc: Error parsing file: expected SEPARATOR or string, got NOTSEPARATOR
|
; PMENU4: llvm-rc: Error parsing file: expected SEPARATOR or string, got NOTSEPARATOR
|
||||||
|
|
||||||
|
|
||||||
|
; RUN: not llvm-rc /V %p/Inputs/parser-dialog-cant-give-helpid.rc 2>&1 | FileCheck %s --check-prefix PDIALOG1
|
||||||
|
|
||||||
|
; PDIALOG1: llvm-rc: Error parsing file: expected identifier, got ,
|
||||||
|
|
||||||
|
|
||||||
|
; RUN: not llvm-rc /V %p/Inputs/parser-dialog-too-few-args.rc 2>&1 | FileCheck %s --check-prefix PDIALOG2
|
||||||
|
|
||||||
|
; PDIALOG2: llvm-rc: Error parsing file: expected ',', got }
|
||||||
|
|
||||||
|
|
||||||
|
; RUN: not llvm-rc /V %p/Inputs/parser-dialog-too-many-args.rc 2>&1 | FileCheck %s --check-prefix PDIALOG3
|
||||||
|
|
||||||
|
; PDIALOG3: llvm-rc: Error parsing file: expected identifier, got ,
|
||||||
|
|
||||||
|
|
||||||
|
; RUN: not llvm-rc /V %p/Inputs/parser-dialog-unknown-type.rc 2>&1 | FileCheck %s --check-prefix PDIALOG4
|
||||||
|
|
||||||
|
; PDIALOG4: llvm-rc: Error parsing file: expected control type, END or '}', got UNKNOWN
|
||||||
|
|
||||||
|
|
||||||
|
; RUN: not llvm-rc /V %p/Inputs/parser-dialog-unnecessary-string.rc 2>&1 | FileCheck %s --check-prefix PDIALOG5
|
||||||
|
|
||||||
|
; PDIALOG5: llvm-rc: Error parsing file: expected integer, got "This shouldn't be here"
|
||||||
|
|
|
@ -67,6 +67,10 @@ RCParser::ParseType RCParser::parseSingleResource() {
|
||||||
Result = parseAcceleratorsResource();
|
Result = parseAcceleratorsResource();
|
||||||
else if (TypeToken->equalsLower("CURSOR"))
|
else if (TypeToken->equalsLower("CURSOR"))
|
||||||
Result = parseCursorResource();
|
Result = parseCursorResource();
|
||||||
|
else if (TypeToken->equalsLower("DIALOG"))
|
||||||
|
Result = parseDialogResource(false);
|
||||||
|
else if (TypeToken->equalsLower("DIALOGEX"))
|
||||||
|
Result = parseDialogResource(true);
|
||||||
else if (TypeToken->equalsLower("ICON"))
|
else if (TypeToken->equalsLower("ICON"))
|
||||||
Result = parseIconResource();
|
Result = parseIconResource();
|
||||||
else if (TypeToken->equalsLower("HTML"))
|
else if (TypeToken->equalsLower("HTML"))
|
||||||
|
@ -235,17 +239,26 @@ Expected<OptionalStmtList> RCParser::parseOptionalStatements(bool IsExtended) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<std::unique_ptr<OptionalStmt>>
|
Expected<std::unique_ptr<OptionalStmt>>
|
||||||
RCParser::parseSingleOptionalStatement(bool) {
|
RCParser::parseSingleOptionalStatement(bool IsExtended) {
|
||||||
ASSIGN_OR_RETURN(TypeToken, readIdentifier());
|
ASSIGN_OR_RETURN(TypeToken, readIdentifier());
|
||||||
if (TypeToken->equals_lower("CHARACTERISTICS"))
|
if (TypeToken->equals_lower("CHARACTERISTICS"))
|
||||||
return parseCharacteristicsStmt();
|
return parseCharacteristicsStmt();
|
||||||
else if (TypeToken->equals_lower("LANGUAGE"))
|
if (TypeToken->equals_lower("LANGUAGE"))
|
||||||
return parseLanguageStmt();
|
return parseLanguageStmt();
|
||||||
else if (TypeToken->equals_lower("VERSION"))
|
if (TypeToken->equals_lower("VERSION"))
|
||||||
return parseVersionStmt();
|
return parseVersionStmt();
|
||||||
else
|
|
||||||
return getExpectedError("optional statement type, BEGIN or '{'",
|
if (IsExtended) {
|
||||||
/* IsAlreadyRead = */ true);
|
if (TypeToken->equals_lower("CAPTION"))
|
||||||
|
return parseCaptionStmt();
|
||||||
|
if (TypeToken->equals_lower("FONT"))
|
||||||
|
return parseFontStmt();
|
||||||
|
if (TypeToken->equals_lower("STYLE"))
|
||||||
|
return parseStyleStmt();
|
||||||
|
}
|
||||||
|
|
||||||
|
return getExpectedError("optional statement type, BEGIN or '{'",
|
||||||
|
/* IsAlreadyRead = */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
RCParser::ParseType RCParser::parseLanguageResource() {
|
RCParser::ParseType RCParser::parseLanguageResource() {
|
||||||
|
@ -277,6 +290,68 @@ RCParser::ParseType RCParser::parseCursorResource() {
|
||||||
return make_unique<CursorResource>(*Arg);
|
return make_unique<CursorResource>(*Arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RCParser::ParseType RCParser::parseDialogResource(bool IsExtended) {
|
||||||
|
// Dialog resources have the following format of the arguments:
|
||||||
|
// DIALOG: x, y, width, height [opt stmts...] {controls...}
|
||||||
|
// DIALOGEX: x, y, width, height [, helpID] [opt stmts...] {controls...}
|
||||||
|
// These are very similar, so we parse them together.
|
||||||
|
ASSIGN_OR_RETURN(LocResult, readIntsWithCommas(4, 4));
|
||||||
|
|
||||||
|
uint32_t HelpID = 0; // When HelpID is unset, it's assumed to be 0.
|
||||||
|
if (IsExtended && consumeOptionalType(Kind::Comma)) {
|
||||||
|
ASSIGN_OR_RETURN(HelpIDResult, readInt());
|
||||||
|
HelpID = *HelpIDResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSIGN_OR_RETURN(OptStatements,
|
||||||
|
parseOptionalStatements(/*UseExtendedStmts = */ true));
|
||||||
|
|
||||||
|
assert(isNextTokenKind(Kind::BlockBegin) &&
|
||||||
|
"parseOptionalStatements, when successful, halts on BlockBegin.");
|
||||||
|
consume();
|
||||||
|
|
||||||
|
auto Dialog = make_unique<DialogResource>(
|
||||||
|
(*LocResult)[0], (*LocResult)[1], (*LocResult)[2], (*LocResult)[3],
|
||||||
|
HelpID, std::move(*OptStatements), IsExtended);
|
||||||
|
|
||||||
|
while (!consumeOptionalType(Kind::BlockEnd)) {
|
||||||
|
ASSIGN_OR_RETURN(ControlDefResult, parseControl());
|
||||||
|
Dialog->addControl(std::move(*ControlDefResult));
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move(Dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
Expected<Control> RCParser::parseControl() {
|
||||||
|
// Each control definition (except CONTROL) follows one of the schemes below
|
||||||
|
// depending on the control class:
|
||||||
|
// [class] text, id, x, y, width, height [, style] [, exstyle] [, helpID]
|
||||||
|
// [class] id, x, y, width, height [, style] [, exstyle] [, helpID]
|
||||||
|
// Note that control ids must be integers.
|
||||||
|
ASSIGN_OR_RETURN(ClassResult, readIdentifier());
|
||||||
|
StringRef ClassUpper = ClassResult->upper();
|
||||||
|
if (Control::SupportedCtls.find(ClassUpper) == Control::SupportedCtls.end())
|
||||||
|
return getExpectedError("control type, END or '}'", true);
|
||||||
|
|
||||||
|
// Read caption if necessary.
|
||||||
|
StringRef Caption;
|
||||||
|
if (Control::CtlsWithTitle.find(ClassUpper) != Control::CtlsWithTitle.end()) {
|
||||||
|
ASSIGN_OR_RETURN(CaptionResult, readString());
|
||||||
|
RETURN_IF_ERROR(consumeType(Kind::Comma));
|
||||||
|
Caption = *CaptionResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSIGN_OR_RETURN(Args, readIntsWithCommas(5, 8));
|
||||||
|
|
||||||
|
auto TakeOptArg = [&Args](size_t Id) -> Optional<uint32_t> {
|
||||||
|
return Args->size() > Id ? (*Args)[Id] : Optional<uint32_t>();
|
||||||
|
};
|
||||||
|
|
||||||
|
return Control(*ClassResult, Caption, (*Args)[0], (*Args)[1], (*Args)[2],
|
||||||
|
(*Args)[3], (*Args)[4], TakeOptArg(5), TakeOptArg(6),
|
||||||
|
TakeOptArg(7));
|
||||||
|
}
|
||||||
|
|
||||||
RCParser::ParseType RCParser::parseIconResource() {
|
RCParser::ParseType RCParser::parseIconResource() {
|
||||||
ASSIGN_OR_RETURN(Arg, readString());
|
ASSIGN_OR_RETURN(Arg, readString());
|
||||||
return make_unique<IconResource>(*Arg);
|
return make_unique<IconResource>(*Arg);
|
||||||
|
@ -386,6 +461,23 @@ RCParser::ParseOptionType RCParser::parseVersionStmt() {
|
||||||
return make_unique<VersionStmt>(*Arg);
|
return make_unique<VersionStmt>(*Arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RCParser::ParseOptionType RCParser::parseCaptionStmt() {
|
||||||
|
ASSIGN_OR_RETURN(Arg, readString());
|
||||||
|
return make_unique<CaptionStmt>(*Arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
RCParser::ParseOptionType RCParser::parseFontStmt() {
|
||||||
|
ASSIGN_OR_RETURN(SizeResult, readInt());
|
||||||
|
RETURN_IF_ERROR(consumeType(Kind::Comma));
|
||||||
|
ASSIGN_OR_RETURN(NameResult, readString());
|
||||||
|
return make_unique<FontStmt>(*SizeResult, *NameResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
RCParser::ParseOptionType RCParser::parseStyleStmt() {
|
||||||
|
ASSIGN_OR_RETURN(Arg, readInt());
|
||||||
|
return make_unique<StyleStmt>(*Arg);
|
||||||
|
}
|
||||||
|
|
||||||
Error RCParser::getExpectedError(const Twine Message, bool IsAlreadyRead) {
|
Error RCParser::getExpectedError(const Twine Message, bool IsAlreadyRead) {
|
||||||
return make_error<ParserError>(
|
return make_error<ParserError>(
|
||||||
Message, IsAlreadyRead ? std::prev(CurLoc) : CurLoc, End);
|
Message, IsAlreadyRead ? std::prev(CurLoc) : CurLoc, End);
|
||||||
|
|
|
@ -128,11 +128,15 @@ private:
|
||||||
ParseType parseLanguageResource();
|
ParseType parseLanguageResource();
|
||||||
ParseType parseAcceleratorsResource();
|
ParseType parseAcceleratorsResource();
|
||||||
ParseType parseCursorResource();
|
ParseType parseCursorResource();
|
||||||
|
ParseType parseDialogResource(bool IsExtended);
|
||||||
ParseType parseIconResource();
|
ParseType parseIconResource();
|
||||||
ParseType parseHTMLResource();
|
ParseType parseHTMLResource();
|
||||||
ParseType parseMenuResource();
|
ParseType parseMenuResource();
|
||||||
ParseType parseStringTableResource();
|
ParseType parseStringTableResource();
|
||||||
|
|
||||||
|
// Helper DIALOG parser - a single control.
|
||||||
|
Expected<Control> parseControl();
|
||||||
|
|
||||||
// Helper MENU parser.
|
// Helper MENU parser.
|
||||||
Expected<MenuDefinitionList> parseMenuItemsList();
|
Expected<MenuDefinitionList> parseMenuItemsList();
|
||||||
|
|
||||||
|
@ -140,6 +144,9 @@ private:
|
||||||
ParseOptionType parseLanguageStmt();
|
ParseOptionType parseLanguageStmt();
|
||||||
ParseOptionType parseCharacteristicsStmt();
|
ParseOptionType parseCharacteristicsStmt();
|
||||||
ParseOptionType parseVersionStmt();
|
ParseOptionType parseVersionStmt();
|
||||||
|
ParseOptionType parseCaptionStmt();
|
||||||
|
ParseOptionType parseFontStmt();
|
||||||
|
ParseOptionType parseStyleStmt();
|
||||||
|
|
||||||
// Raises an error. If IsAlreadyRead = false (default), this complains about
|
// Raises an error. If IsAlreadyRead = false (default), this complains about
|
||||||
// the token that couldn't be parsed. If the flag is on, this complains about
|
// the token that couldn't be parsed. If the flag is on, this complains about
|
||||||
|
|
|
@ -113,6 +113,35 @@ raw_ostream &StringTableResource::log(raw_ostream &OS) const {
|
||||||
return OS;
|
return OS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const StringSet<> Control::SupportedCtls = {
|
||||||
|
"LTEXT", "RTEXT", "CTEXT", "PUSHBUTTON", "DEFPUSHBUTTON", "EDITTEXT"};
|
||||||
|
|
||||||
|
const StringSet<> Control::CtlsWithTitle = {"LTEXT", "RTEXT", "CTEXT",
|
||||||
|
"PUSHBUTTON", "DEFPUSHBUTTON"};
|
||||||
|
|
||||||
|
raw_ostream &Control::log(raw_ostream &OS) const {
|
||||||
|
OS << " Control (" << ID << "): " << Type << ", title: " << Title
|
||||||
|
<< ", loc: (" << X << ", " << Y << "), size: [" << Width << ", " << Height
|
||||||
|
<< "]";
|
||||||
|
if (Style)
|
||||||
|
OS << ", style: " << *Style;
|
||||||
|
if (ExtStyle)
|
||||||
|
OS << ", ext. style: " << *ExtStyle;
|
||||||
|
if (HelpID)
|
||||||
|
OS << ", help ID: " << *HelpID;
|
||||||
|
return OS << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
raw_ostream &DialogResource::log(raw_ostream &OS) const {
|
||||||
|
OS << "Dialog" << (IsExtended ? "Ex" : "") << " (" << ResName << "): loc: ("
|
||||||
|
<< X << ", " << Y << "), size: [" << Width << ", " << Height
|
||||||
|
<< "], help ID: " << HelpID << "\n";
|
||||||
|
OptStatements.log(OS);
|
||||||
|
for (auto &Ctl : Controls)
|
||||||
|
Ctl.log(OS);
|
||||||
|
return OS;
|
||||||
|
}
|
||||||
|
|
||||||
raw_ostream &CharacteristicsStmt::log(raw_ostream &OS) const {
|
raw_ostream &CharacteristicsStmt::log(raw_ostream &OS) const {
|
||||||
return OS << "Characteristics: " << Value << "\n";
|
return OS << "Characteristics: " << Value << "\n";
|
||||||
}
|
}
|
||||||
|
@ -121,5 +150,17 @@ raw_ostream &VersionStmt::log(raw_ostream &OS) const {
|
||||||
return OS << "Version: " << Value << "\n";
|
return OS << "Version: " << Value << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
raw_ostream &CaptionStmt::log(raw_ostream &OS) const {
|
||||||
|
return OS << "Caption: " << Value << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
raw_ostream &FontStmt::log(raw_ostream &OS) const {
|
||||||
|
return OS << "Font: size = " << Size << ", face = " << Typeface << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
raw_ostream &StyleStmt::log(raw_ostream &OS) const {
|
||||||
|
return OS << "Style: " << Value << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace rc
|
} // namespace rc
|
||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
#include "ResourceScriptToken.h"
|
#include "ResourceScriptToken.h"
|
||||||
|
|
||||||
|
#include "llvm/ADT/StringSet.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace rc {
|
namespace rc {
|
||||||
|
|
||||||
|
@ -268,6 +270,55 @@ public:
|
||||||
raw_ostream &log(raw_ostream &) const override;
|
raw_ostream &log(raw_ostream &) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// -- DIALOG(EX) resource and its helper classes --
|
||||||
|
//
|
||||||
|
// This resource describes dialog boxes and controls residing inside them.
|
||||||
|
//
|
||||||
|
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381003(v=vs.85).aspx
|
||||||
|
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381002(v=vs.85).aspx
|
||||||
|
|
||||||
|
// Single control definition.
|
||||||
|
class Control {
|
||||||
|
StringRef Type, Title;
|
||||||
|
uint32_t ID, X, Y, Width, Height;
|
||||||
|
Optional<uint32_t> Style, ExtStyle, HelpID;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Control(StringRef CtlType, StringRef CtlTitle, uint32_t CtlID, uint32_t PosX,
|
||||||
|
uint32_t PosY, uint32_t ItemWidth, uint32_t ItemHeight,
|
||||||
|
Optional<uint32_t> ItemStyle, Optional<uint32_t> ExtItemStyle,
|
||||||
|
Optional<uint32_t> CtlHelpID)
|
||||||
|
: Type(CtlType), Title(CtlTitle), ID(CtlID), X(PosX), Y(PosY),
|
||||||
|
Width(ItemWidth), Height(ItemHeight), Style(ItemStyle),
|
||||||
|
ExtStyle(ExtItemStyle), HelpID(CtlHelpID) {}
|
||||||
|
|
||||||
|
static const StringSet<> SupportedCtls;
|
||||||
|
static const StringSet<> CtlsWithTitle;
|
||||||
|
|
||||||
|
raw_ostream &log(raw_ostream &) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Single dialog definition. We don't create distinct classes for DIALOG and
|
||||||
|
// DIALOGEX because of their being too similar to each other. We only have a
|
||||||
|
// flag determining the type of the dialog box.
|
||||||
|
class DialogResource : public RCResource {
|
||||||
|
uint32_t X, Y, Width, Height, HelpID;
|
||||||
|
OptionalStmtList OptStatements;
|
||||||
|
std::vector<Control> Controls;
|
||||||
|
bool IsExtended;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DialogResource(uint32_t PosX, uint32_t PosY, uint32_t DlgWidth,
|
||||||
|
uint32_t DlgHeight, uint32_t DlgHelpID,
|
||||||
|
OptionalStmtList &&OptStmts, bool IsDialogEx)
|
||||||
|
: X(PosX), Y(PosY), Width(DlgWidth), Height(DlgHeight), HelpID(DlgHelpID),
|
||||||
|
OptStatements(std::move(OptStmts)), IsExtended(IsDialogEx) {}
|
||||||
|
|
||||||
|
void addControl(Control &&Ctl) { Controls.push_back(std::move(Ctl)); }
|
||||||
|
|
||||||
|
raw_ostream &log(raw_ostream &) const override;
|
||||||
|
};
|
||||||
|
|
||||||
// CHARACTERISTICS optional statement.
|
// CHARACTERISTICS optional statement.
|
||||||
//
|
//
|
||||||
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380872(v=vs.85).aspx
|
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380872(v=vs.85).aspx
|
||||||
|
@ -290,6 +341,44 @@ public:
|
||||||
raw_ostream &log(raw_ostream &) const override;
|
raw_ostream &log(raw_ostream &) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// CAPTION optional statement.
|
||||||
|
//
|
||||||
|
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380778(v=vs.85).aspx
|
||||||
|
class CaptionStmt : public OptionalStmt {
|
||||||
|
StringRef Value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CaptionStmt(StringRef Caption) : Value(Caption) {}
|
||||||
|
raw_ostream &log(raw_ostream &) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
// FONT optional statement.
|
||||||
|
// Note that the documentation is inaccurate: it expects five arguments to be
|
||||||
|
// given, however the example provides only two. In fact, the original tool
|
||||||
|
// expects two arguments - point size and name of the typeface.
|
||||||
|
//
|
||||||
|
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381013(v=vs.85).aspx
|
||||||
|
class FontStmt : public OptionalStmt {
|
||||||
|
uint32_t Size;
|
||||||
|
StringRef Typeface;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FontStmt(uint32_t FontSize, StringRef FontName)
|
||||||
|
: Size(FontSize), Typeface(FontName) {}
|
||||||
|
raw_ostream &log(raw_ostream &) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
// STYLE optional statement.
|
||||||
|
//
|
||||||
|
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381051(v=vs.85).aspx
|
||||||
|
class StyleStmt : public OptionalStmt {
|
||||||
|
uint32_t Value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
StyleStmt(uint32_t Style) : Value(Style) {}
|
||||||
|
raw_ostream &log(raw_ostream &) const override;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace rc
|
} // namespace rc
|
||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue