Skip to content

Commit

Permalink
Merge pull request #2055 from ivan-mogilko/ags4--support-lf-properties
Browse files Browse the repository at this point in the history
Editor: unescape text properties when writing game data
  • Loading branch information
ivan-mogilko authored Jul 12, 2023
2 parents 40a7fc9 + 3a1cec1 commit 2abcf82
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 20 deletions.
2 changes: 1 addition & 1 deletion Common/util/string_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ namespace StrUtil
// returns def_val on failure
float StringToFloat(const String &s, float def_val = 0.f);

// A simple unescape string implementation, unescapes '\\x' into '\x'.
// A simple unescape string implementation, unescapes "\\x" into '\x'.
String Unescape(const String &s);
// Converts a classic wildcard search pattern into C++11 compatible regex pattern
String WildcardToRegex(const String &wildcard);
Expand Down
34 changes: 23 additions & 11 deletions Editor/AGS.Editor/DataFileWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace AGS.Editor
{
Expand Down Expand Up @@ -283,6 +284,17 @@ static void FilePutNullTerminatedString(string text, BinaryWriter writer)
writer.Write(GetTextBytesTerminated(text));
}

/// <summary>
/// Applies necessary transformations for the properties with
/// human-readable text, such as:
/// - unescapes special sequences ("\\n" to '\n'), etc.
/// </summary>
/// <param name="text"></param>
public static string TextProperty(string text)
{
return Regex.Unescape(text);
}

/// <summary>
/// Write asset library header with the table of contents.
/// Currently corresponds to writing main lib file in chain in format version 30.
Expand Down Expand Up @@ -528,7 +540,7 @@ public static string MakeFlatDataFile(string[] assetFileNames, int splitSize, st
private static void WriteGameSetupStructBase_Aligned(BinaryWriter writer, Game game)
{
// assume stream is aligned at start
WriteString(SafeTruncate(game.Settings.GameName, 49), 50, writer);
WriteString(SafeTruncate(TextProperty(game.Settings.GameName), 49), 50, writer);
writer.Write(new byte[2]); // alignment padding
int[] options = new int[100];
options[NativeConstants.GameOptions.OPT_ALWAYSSPCH] = (game.Settings.AlwaysDisplayTextAsSpeech ? 1 : 0);
Expand Down Expand Up @@ -688,7 +700,7 @@ public static void Write(BinaryWriter writer, CustomProperties properties)
foreach (KeyValuePair<string, CustomProperty> pair in properties.PropertyValues)
{
FilePutString(pair.Value.Name, writer);
FilePutString(pair.Value.Value, writer);
FilePutString(TextProperty(pair.Value.Value), writer);
}
}
}
Expand Down Expand Up @@ -767,7 +779,7 @@ public void Serialize(BinaryWriter writer)
for (int i = 0; i < PropertyCount; ++i)
{
FilePutString(Names[i], writer);
FilePutString(Values[i], writer);
FilePutString(TextProperty(Values[i]), writer);
}
}

Expand Down Expand Up @@ -1139,7 +1151,7 @@ private void WriteAllButtonsAndTextWindowEdges()
writer.Write(0); // rightclick
writer.Write(ctrl.NewModeNumber); // lclickdata
writer.Write(0); // rclickdata
FilePutString(ctrl.Text, writer); // text
FilePutString(TextProperty(ctrl.Text), writer); // text
writer.Write((int)ctrl.TextAlignment); // textAlignment
}
}
Expand All @@ -1151,7 +1163,7 @@ private void WriteAllLabels()
{
WriteGUIControl(label, 0);
string text = label.Text;
FilePutString(text, writer);
FilePutString(TextProperty(text), writer);
writer.Write(label.Font);
writer.Write(label.TextColor);
writer.Write((int)label.TextAlignment);
Expand Down Expand Up @@ -1191,7 +1203,7 @@ private void WriteAllTextBoxes()
foreach (GUITextBox textBox in GUITextBoxes)
{
WriteGUIControl(textBox, 0, new string[] { textBox.OnActivate });
FilePutString(textBox.Text, writer);
FilePutString(TextProperty(textBox.Text), writer);
writer.Write(textBox.Font);
writer.Write(textBox.TextColor);
writer.Write(MakeTextBoxFlags(textBox));
Expand Down Expand Up @@ -1459,7 +1471,7 @@ public static bool SaveThisGameToFile(string fileName, Game game, CompileMessage
writer.Write(new byte[68]); // inventory item slot 0 is unused
for (int i = 0; i < game.InventoryItems.Count; ++i)
{
WriteString(game.InventoryItems[i].Description, 24, writer);
WriteString(TextProperty(game.InventoryItems[i].Description), 24, writer);
writer.Write(new byte[4]); // null terminator plus 3 bytes padding
writer.Write(game.InventoryItems[i].Image);
writer.Write(game.InventoryItems[i].CursorImage);
Expand Down Expand Up @@ -1606,7 +1618,7 @@ public static bool SaveThisGameToFile(string fileName, Game game, CompileMessage
}
writer.Write((short)0); // actx
writer.Write((short)0); // acty
WriteString(character.RealName, 40, writer); // name
WriteString(TextProperty(character.RealName), 40, writer); // name
WriteString(character.ScriptName, NativeConstants.MAX_SCRIPT_NAME_LEN, writer); // scrname
writer.Write((char)1); // on
writer.Write((byte)0); // alignment padding
Expand Down Expand Up @@ -1666,8 +1678,8 @@ public static bool SaveThisGameToFile(string fileName, Game game, CompileMessage
{
FilePutString(schemaItem.Name, writer);
writer.Write((int)schemaItem.Type);
FilePutString(schemaItem.Description, writer);
FilePutString(schemaItem.DefaultValue, writer);
FilePutString(TextProperty(schemaItem.Description), writer);
FilePutString(TextProperty(schemaItem.DefaultValue), writer);
}
for (int i = 0; i < game.Characters.Count; ++i)
{
Expand Down Expand Up @@ -1739,7 +1751,7 @@ public static bool SaveThisGameToFile(string fileName, Game game, CompileMessage
writer.Write(room.Number);
if (room.Description != null)
{
FilePutNullTerminatedString(room.Description, 500, writer);
FilePutNullTerminatedString(TextProperty(room.Description), 500, writer);
}
else writer.Write((byte)0);
}
Expand Down
9 changes: 9 additions & 0 deletions Editor/AGS.Native/NativeMethods.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ see the license.txt for details.
#include "game/plugininfo.h"
#include "util/error.h"
#include "util/multifilelib.h"
#include "util/string_utils.h"

using namespace System::Runtime::InteropServices;
using namespace AGS::Native;
Expand Down Expand Up @@ -112,6 +113,14 @@ AGSString TextConverter::Convert(System::String^ clr_str)
return TextHelper::Convert(clr_str, _encoding);
}

AGSString TextConverter::ConvertTextProperty(System::String^ clr_str)
{
if (clr_str == nullptr)
return AGSString();
AGSString str = TextHelper::Convert(clr_str, _encoding);
return AGS::Common::StrUtil::Unescape(str);
}

std::string TextConverter::ConvertToStd(System::String^ clr_str)
{
if (clr_str == nullptr)
Expand Down
10 changes: 8 additions & 2 deletions Editor/AGS.Native/NativeUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,15 @@ public ref class TextConverter
System::Text::Encoding^ GetEncoding();
// Convert native string to managed using current encoding
System::String^ Convert(const AGS::Common::String &str);
// Convert managed string to native using current encoding
// Convert managed string to native using current encoding;
// this is meant for strings containing human-readable texts
AGSString Convert(System::String^ clr_str);
// Convert managed string to native std::string using current encoding
// Converts a textual property from managed string to native using current encoding;
// Does additional transformation for human-readable text:
// - unescapes special sequences ("\\n" to '\n')
AGSString ConvertTextProperty(System::String^ clr_str);
// Convert managed string to native std::string using current encoding;
// this is meant for strings containing human-readable texts
std::string ConvertToStd(System::String^ clr_str);

private:
Expand Down
12 changes: 6 additions & 6 deletions Editor/AGS.Native/agsnative.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2131,7 +2131,7 @@ void ConvertGUIToBinaryFormat(GUI ^guiObj, GUIMain *gui)
nbut.ClickAction[Common::kGUIClickLeft] = (Common::GUIClickAction)button->ClickAction;
nbut.ClickData[Common::kGUIClickLeft] = button->NewModeNumber;
nbut.SetClipImage(button->ClipImage);
nbut.SetText(tcv->Convert(button->Text));
nbut.SetText(tcv->ConvertTextProperty(button->Text));
nbut.EventHandlers[0] = TextHelper::ConvertASCII(button->OnClick);
guibuts.push_back(nbut);

Expand All @@ -2143,7 +2143,7 @@ void ConvertGUIToBinaryFormat(GUI ^guiObj, GUIMain *gui)
nlabel.TextColor = label->TextColor;
nlabel.Font = label->Font;
nlabel.TextAlignment = (::HorAlignment)label->TextAlignment;
Common::String text = tcv->Convert(label->Text);
Common::String text = tcv->ConvertTextProperty(label->Text);
nlabel.SetText(text);
guilabels.push_back(nlabel);

Expand Down Expand Up @@ -2283,7 +2283,7 @@ void CompileCustomProperties(AGS::Types::CustomProperties ^convertFrom, AGS::Com
{
AGS::Common::String name, value;
name = TextHelper::ConvertASCII(convertFrom->PropertyValues[key]->Name); // property name is ASCII
value = tcv->Convert(convertFrom->PropertyValues[key]->Value);
value = tcv->ConvertTextProperty(convertFrom->PropertyValues[key]->Value);
(*compileInto)[name] = value;
}
}
Expand Down Expand Up @@ -2940,7 +2940,7 @@ void convert_room_to_native(Room ^room, RoomStruct &rs)
for (size_t i = 0; i < rs.MessageCount; ++i)
{
RoomMessage ^newMessage = room->Messages[i];
rs.Messages[i] = tcv->Convert(newMessage->Text);
rs.Messages[i] = tcv->ConvertTextProperty(newMessage->Text);
if (newMessage->ShowAsSpeech)
{
rs.MessageInfos[i].DisplayAs = newMessage->CharacterID + 1;
Expand All @@ -2966,7 +2966,7 @@ void convert_room_to_native(Room ^room, RoomStruct &rs)
rs.Objects[i].Y = obj->StartY;
rs.Objects[i].IsOn = obj->Visible;
rs.Objects[i].Baseline = obj->Baseline;
rs.Objects[i].Name = tcv->Convert(obj->Description);
rs.Objects[i].Name = tcv->ConvertTextProperty(obj->Description);
rs.Objects[i].Flags = 0;
if (obj->UseRoomAreaScaling) rs.Objects[i].Flags |= OBJF_USEROOMSCALING;
if (obj->UseRoomAreaLighting) rs.Objects[i].Flags |= OBJF_USEREGIONTINTS;
Expand All @@ -2978,7 +2978,7 @@ void convert_room_to_native(Room ^room, RoomStruct &rs)
for (size_t i = 0; i < rs.HotspotCount; ++i)
{
RoomHotspot ^hotspot = room->Hotspots[i];
rs.Hotspots[i].Name = tcv->Convert(hotspot->Description);
rs.Hotspots[i].Name = tcv->ConvertTextProperty(hotspot->Description);
rs.Hotspots[i].ScriptName = TextHelper::ConvertASCII(hotspot->Name);
rs.Hotspots[i].WalkTo.X = hotspot->WalkToPoint.X;
rs.Hotspots[i].WalkTo.Y = hotspot->WalkToPoint.Y;
Expand Down

0 comments on commit 2abcf82

Please sign in to comment.