summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-rc/ResourceFileWriter.cpp
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2017-10-06 20:51:20 +0000
committerZachary Turner <zturner@google.com>2017-10-06 20:51:20 +0000
commit420090af89bacc97ce9c9c28eb3d32d0c704ca53 (patch)
treee7e7c3a236813be6ef8dfdcde0f3c7f1ba847fdf /llvm/tools/llvm-rc/ResourceFileWriter.cpp
parente9baea817822ec183f521c444b37d257aabbc655 (diff)
downloadbcm5719-llvm-420090af89bacc97ce9c9c28eb3d32d0c704ca53.tar.gz
bcm5719-llvm-420090af89bacc97ce9c9c28eb3d32d0c704ca53.zip
[llvm-rc] Add optional serialization support for DIALOG(EX) resources.
This is part 5 of llvm-rc serialization support. This allows DIALOG and DIALOGEX to serialize if dialog-specific optional statements are provided. These are (as of now): CAPTION, FONT, and STYLE. Notably, FONT statement can take more than two arguments when describing DIALOGEX resources (as in msdn.microsoft.com/en-us/library/windows/desktop/aa381013.aspx). I made some changes to the parser to reflect this fact. Patch by Marek Sokolowski Differential Revision: https://reviews.llvm.org/D37864 llvm-svn: 315104
Diffstat (limited to 'llvm/tools/llvm-rc/ResourceFileWriter.cpp')
-rw-r--r--llvm/tools/llvm-rc/ResourceFileWriter.cpp67
1 files changed, 62 insertions, 5 deletions
diff --git a/llvm/tools/llvm-rc/ResourceFileWriter.cpp b/llvm/tools/llvm-rc/ResourceFileWriter.cpp
index 701c4449ffa..243b3da404b 100644
--- a/llvm/tools/llvm-rc/ResourceFileWriter.cpp
+++ b/llvm/tools/llvm-rc/ResourceFileWriter.cpp
@@ -224,6 +224,11 @@ Error ResourceFileWriter::visitDialogResource(const RCResource *Res) {
return writeResource(Res, &ResourceFileWriter::writeDialogBody);
}
+Error ResourceFileWriter::visitCaptionStmt(const CaptionStmt *Stmt) {
+ ObjectData.Caption = Stmt->Value;
+ return Error::success();
+}
+
Error ResourceFileWriter::visitHTMLResource(const RCResource *Res) {
return writeResource(Res, &ResourceFileWriter::writeHTMLBody);
}
@@ -238,6 +243,16 @@ Error ResourceFileWriter::visitCharacteristicsStmt(
return Error::success();
}
+Error ResourceFileWriter::visitFontStmt(const FontStmt *Stmt) {
+ RETURN_IF_ERROR(checkNumberFits<uint16_t>(Stmt->Size, "Font size"));
+ RETURN_IF_ERROR(checkNumberFits<uint16_t>(Stmt->Weight, "Font weight"));
+ RETURN_IF_ERROR(checkNumberFits<uint8_t>(Stmt->Charset, "Font charset"));
+ ObjectInfo::FontInfo Font{Stmt->Size, Stmt->Name, Stmt->Weight, Stmt->Italic,
+ Stmt->Charset};
+ ObjectData.Font.emplace(Font);
+ return Error::success();
+}
+
Error ResourceFileWriter::visitLanguageStmt(const LanguageResource *Stmt) {
RETURN_IF_ERROR(checkNumberFits(Stmt->Lang, 10, "Primary language ID"));
RETURN_IF_ERROR(checkNumberFits(Stmt->SubLang, 6, "Sublanguage ID"));
@@ -245,6 +260,11 @@ Error ResourceFileWriter::visitLanguageStmt(const LanguageResource *Stmt) {
return Error::success();
}
+Error ResourceFileWriter::visitStyleStmt(const StyleStmt *Stmt) {
+ ObjectData.Style = Stmt->Value;
+ return Error::success();
+}
+
Error ResourceFileWriter::visitVersionStmt(const VersionStmt *Stmt) {
ObjectData.VersionInfo = Stmt->Value;
return Error::success();
@@ -474,10 +494,36 @@ Error ResourceFileWriter::writeDialogBody(const RCResource *Base) {
auto *Res = cast<DialogResource>(Base);
// Default style: WS_POPUP | WS_BORDER | WS_SYSMENU.
- const uint32_t UsedStyle = 0x80880000;
+ const uint32_t DefaultStyle = 0x80880000;
+ const uint32_t StyleFontFlag = 0x40;
+ const uint32_t StyleCaptionFlag = 0x00C00000;
+
+ uint32_t UsedStyle = ObjectData.Style.getValueOr(DefaultStyle);
+ if (ObjectData.Font)
+ UsedStyle |= StyleFontFlag;
+ else
+ UsedStyle &= ~StyleFontFlag;
+
+ // Actually, in case of empty (but existent) caption, the examined field
+ // is equal to "\"\"". That's why empty captions are still noticed.
+ if (ObjectData.Caption != "")
+ UsedStyle |= StyleCaptionFlag;
+
+ const uint16_t DialogExMagic = 0xFFFF;
// Write DIALOG(EX) header prefix. These are pretty different.
if (!Res->IsExtended) {
+ // We cannot let the higher word of DefaultStyle be equal to 0xFFFF.
+ // In such a case, whole object (in .res file) is equivalent to a
+ // DIALOGEX. It might lead to access violation/segmentation fault in
+ // resource readers. For example,
+ // 1 DIALOG 0, 0, 0, 65432
+ // STYLE 0xFFFF0001 {}
+ // would be compiled to a DIALOGEX with 65432 controls.
+ if ((UsedStyle >> 16) == DialogExMagic)
+ return createError("16 higher bits of DIALOG resource style cannot be"
+ " equal to 0xFFFF");
+
struct {
ulittle32_t Style;
ulittle32_t ExtStyle;
@@ -486,8 +532,6 @@ Error ResourceFileWriter::writeDialogBody(const RCResource *Base) {
writeObject(Prefix);
} else {
- const uint16_t DialogExMagic = 0xFFFF;
-
struct {
ulittle16_t Version;
ulittle16_t Magic;
@@ -529,8 +573,21 @@ Error ResourceFileWriter::writeDialogBody(const RCResource *Base) {
// Window CLASS field. Not kept here.
writeInt<uint16_t>(0);
- // Window title. There is no title for now, so all we output is '\0'.
- writeInt<uint16_t>(0);
+ // Window title or a single word equal to 0.
+ RETURN_IF_ERROR(writeCString(ObjectData.Caption));
+
+ // If there *is* a window font declared, output its data.
+ auto &Font = ObjectData.Font;
+ if (Font) {
+ writeInt<uint16_t>(Font->Size);
+ // Additional description occurs only in DIALOGEX.
+ if (Res->IsExtended) {
+ writeInt<uint16_t>(Font->Weight);
+ writeInt<uint8_t>(Font->IsItalic);
+ writeInt<uint8_t>(Font->Charset);
+ }
+ RETURN_IF_ERROR(writeCString(Font->Typeface));
+ }
auto handleCtlError = [&](Error &&Err, const Control &Ctl) -> Error {
if (!Err)
OpenPOWER on IntegriCloud