InlineResponses.cs
1 using System.IO; 2 using System.Text; 3 4 namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard 5 { 6 internal class InlineResponses 7 { 8 private const uint MaxStrLenUTF8 = 0x7D4; 9 private const uint MaxStrLenUTF16 = 0x3EC; 10 11 private static void BeginResponse(InlineKeyboardState state, InlineKeyboardResponse resCode, BinaryWriter writer) 12 { 13 writer.Write((uint)state); 14 writer.Write((uint)resCode); 15 } 16 17 private static uint WriteString(string text, BinaryWriter writer, uint maxSize, Encoding encoding) 18 { 19 // Ensure the text fits in the buffer, but do not straight cut the bytes because 20 // this may corrupt the encoding. Search for a cut in the source string that fits. 21 22 byte[] bytes = null; 23 24 for (int maxStr = text.Length; maxStr >= 0; maxStr--) 25 { 26 // This loop will probably will run only once. 27 bytes = encoding.GetBytes(text, 0, maxStr); 28 if (bytes.Length <= maxSize) 29 { 30 break; 31 } 32 } 33 34 writer.Write(bytes); 35 writer.Seek((int)maxSize - bytes.Length, SeekOrigin.Current); 36 writer.Write((uint)text.Length); // String size 37 38 return (uint)text.Length; // Return the cursor position at the end of the text 39 } 40 41 private static void WriteStringWithCursor(string text, uint cursor, BinaryWriter writer, uint maxSize, Encoding encoding, bool padMiddle) 42 { 43 uint length = WriteString(text, writer, maxSize, encoding); 44 45 if (cursor > length) 46 { 47 cursor = length; 48 } 49 50 if (padMiddle) 51 { 52 writer.Write((int)-1); // ? 53 writer.Write((int)-1); // ? 54 } 55 56 writer.Write(cursor); // Cursor position 57 } 58 59 public static byte[] FinishedInitialize(InlineKeyboardState state) 60 { 61 uint resSize = 2 * sizeof(uint) + 0x1; 62 63 using MemoryStream stream = new(new byte[resSize]); 64 using BinaryWriter writer = new(stream); 65 66 BeginResponse(state, InlineKeyboardResponse.FinishedInitialize, writer); 67 writer.Write((byte)1); // Data (ignored by the program) 68 69 return stream.ToArray(); 70 } 71 72 public static byte[] Default(InlineKeyboardState state) 73 { 74 uint resSize = 2 * sizeof(uint); 75 76 using MemoryStream stream = new(new byte[resSize]); 77 using BinaryWriter writer = new(stream); 78 79 BeginResponse(state, InlineKeyboardResponse.Default, writer); 80 81 return stream.ToArray(); 82 } 83 84 public static byte[] ChangedString(string text, uint cursor, InlineKeyboardState state) 85 { 86 uint resSize = 6 * sizeof(uint) + MaxStrLenUTF16; 87 88 using MemoryStream stream = new(new byte[resSize]); 89 using BinaryWriter writer = new(stream); 90 91 BeginResponse(state, InlineKeyboardResponse.ChangedString, writer); 92 WriteStringWithCursor(text, cursor, writer, MaxStrLenUTF16, Encoding.Unicode, true); 93 94 return stream.ToArray(); 95 } 96 97 public static byte[] MovedCursor(string text, uint cursor, InlineKeyboardState state) 98 { 99 uint resSize = 4 * sizeof(uint) + MaxStrLenUTF16; 100 101 using MemoryStream stream = new(new byte[resSize]); 102 using BinaryWriter writer = new(stream); 103 104 BeginResponse(state, InlineKeyboardResponse.MovedCursor, writer); 105 WriteStringWithCursor(text, cursor, writer, MaxStrLenUTF16, Encoding.Unicode, false); 106 107 return stream.ToArray(); 108 } 109 110 public static byte[] MovedTab(string text, uint cursor, InlineKeyboardState state) 111 { 112 // Should be the same as MovedCursor. 113 114 uint resSize = 4 * sizeof(uint) + MaxStrLenUTF16; 115 116 using MemoryStream stream = new(new byte[resSize]); 117 using BinaryWriter writer = new(stream); 118 119 BeginResponse(state, InlineKeyboardResponse.MovedTab, writer); 120 WriteStringWithCursor(text, cursor, writer, MaxStrLenUTF16, Encoding.Unicode, false); 121 122 return stream.ToArray(); 123 } 124 125 public static byte[] DecidedEnter(string text, InlineKeyboardState state) 126 { 127 uint resSize = 3 * sizeof(uint) + MaxStrLenUTF16; 128 129 using MemoryStream stream = new(new byte[resSize]); 130 using BinaryWriter writer = new(stream); 131 132 BeginResponse(state, InlineKeyboardResponse.DecidedEnter, writer); 133 WriteString(text, writer, MaxStrLenUTF16, Encoding.Unicode); 134 135 return stream.ToArray(); 136 } 137 138 public static byte[] DecidedCancel(InlineKeyboardState state) 139 { 140 uint resSize = 2 * sizeof(uint); 141 142 using MemoryStream stream = new(new byte[resSize]); 143 using BinaryWriter writer = new(stream); 144 145 BeginResponse(state, InlineKeyboardResponse.DecidedCancel, writer); 146 147 return stream.ToArray(); 148 } 149 150 public static byte[] ChangedStringUtf8(string text, uint cursor, InlineKeyboardState state) 151 { 152 uint resSize = 6 * sizeof(uint) + MaxStrLenUTF8; 153 154 using MemoryStream stream = new(new byte[resSize]); 155 using BinaryWriter writer = new(stream); 156 157 BeginResponse(state, InlineKeyboardResponse.ChangedStringUtf8, writer); 158 WriteStringWithCursor(text, cursor, writer, MaxStrLenUTF8, Encoding.UTF8, true); 159 160 return stream.ToArray(); 161 } 162 163 public static byte[] MovedCursorUtf8(string text, uint cursor, InlineKeyboardState state) 164 { 165 uint resSize = 4 * sizeof(uint) + MaxStrLenUTF8; 166 167 using MemoryStream stream = new(new byte[resSize]); 168 using BinaryWriter writer = new(stream); 169 170 BeginResponse(state, InlineKeyboardResponse.MovedCursorUtf8, writer); 171 WriteStringWithCursor(text, cursor, writer, MaxStrLenUTF8, Encoding.UTF8, false); 172 173 return stream.ToArray(); 174 } 175 176 public static byte[] DecidedEnterUtf8(string text, InlineKeyboardState state) 177 { 178 uint resSize = 3 * sizeof(uint) + MaxStrLenUTF8; 179 180 using MemoryStream stream = new(new byte[resSize]); 181 using BinaryWriter writer = new(stream); 182 183 BeginResponse(state, InlineKeyboardResponse.DecidedEnterUtf8, writer); 184 WriteString(text, writer, MaxStrLenUTF8, Encoding.UTF8); 185 186 return stream.ToArray(); 187 } 188 189 public static byte[] UnsetCustomizeDic(InlineKeyboardState state) 190 { 191 uint resSize = 2 * sizeof(uint); 192 193 using MemoryStream stream = new(new byte[resSize]); 194 using BinaryWriter writer = new(stream); 195 196 BeginResponse(state, InlineKeyboardResponse.UnsetCustomizeDic, writer); 197 198 return stream.ToArray(); 199 } 200 201 public static byte[] ReleasedUserWordInfo(InlineKeyboardState state) 202 { 203 uint resSize = 2 * sizeof(uint); 204 205 using MemoryStream stream = new(new byte[resSize]); 206 using BinaryWriter writer = new(stream); 207 208 BeginResponse(state, InlineKeyboardResponse.ReleasedUserWordInfo, writer); 209 210 return stream.ToArray(); 211 } 212 213 public static byte[] UnsetCustomizedDictionaries(InlineKeyboardState state) 214 { 215 uint resSize = 2 * sizeof(uint); 216 217 using MemoryStream stream = new(new byte[resSize]); 218 using BinaryWriter writer = new(stream); 219 220 BeginResponse(state, InlineKeyboardResponse.UnsetCustomizedDictionaries, writer); 221 222 return stream.ToArray(); 223 } 224 225 public static byte[] ChangedStringV2(string text, uint cursor, InlineKeyboardState state) 226 { 227 uint resSize = 6 * sizeof(uint) + MaxStrLenUTF16 + 0x1; 228 229 using MemoryStream stream = new(new byte[resSize]); 230 using BinaryWriter writer = new(stream); 231 232 BeginResponse(state, InlineKeyboardResponse.ChangedStringV2, writer); 233 WriteStringWithCursor(text, cursor, writer, MaxStrLenUTF16, Encoding.Unicode, true); 234 writer.Write((byte)0); // Flag == 0 235 236 return stream.ToArray(); 237 } 238 239 public static byte[] MovedCursorV2(string text, uint cursor, InlineKeyboardState state) 240 { 241 uint resSize = 4 * sizeof(uint) + MaxStrLenUTF16 + 0x1; 242 243 using MemoryStream stream = new(new byte[resSize]); 244 using BinaryWriter writer = new(stream); 245 246 BeginResponse(state, InlineKeyboardResponse.MovedCursorV2, writer); 247 WriteStringWithCursor(text, cursor, writer, MaxStrLenUTF16, Encoding.Unicode, false); 248 writer.Write((byte)0); // Flag == 0 249 250 return stream.ToArray(); 251 } 252 253 public static byte[] ChangedStringUtf8V2(string text, uint cursor, InlineKeyboardState state) 254 { 255 uint resSize = 6 * sizeof(uint) + MaxStrLenUTF8 + 0x1; 256 257 using MemoryStream stream = new(new byte[resSize]); 258 using BinaryWriter writer = new(stream); 259 260 BeginResponse(state, InlineKeyboardResponse.ChangedStringUtf8V2, writer); 261 WriteStringWithCursor(text, cursor, writer, MaxStrLenUTF8, Encoding.UTF8, true); 262 writer.Write((byte)0); // Flag == 0 263 264 return stream.ToArray(); 265 } 266 267 public static byte[] MovedCursorUtf8V2(string text, uint cursor, InlineKeyboardState state) 268 { 269 uint resSize = 4 * sizeof(uint) + MaxStrLenUTF8 + 0x1; 270 271 using MemoryStream stream = new(new byte[resSize]); 272 using BinaryWriter writer = new(stream); 273 274 BeginResponse(state, InlineKeyboardResponse.MovedCursorUtf8V2, writer); 275 WriteStringWithCursor(text, cursor, writer, MaxStrLenUTF8, Encoding.UTF8, false); 276 writer.Write((byte)0); // Flag == 0 277 278 return stream.ToArray(); 279 } 280 } 281 }