/ src / Ryujinx.HLE / HOS / Applets / SoftwareKeyboard / InlineResponses.cs
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  }