EditStringDialog.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. // EditStringDialog.cpp : implementation file
  19. //
  20. #include "stdafx.h"
  21. #include "leveledit.h"
  22. #include "editstringdialog.h"
  23. #include "translateobj.h"
  24. #include "definitionclassids.h"
  25. #include "presetmgr.h"
  26. #include "preset.h"
  27. #ifdef _DEBUG
  28. #define new DEBUG_NEW
  29. #undef THIS_FILE
  30. static char THIS_FILE[] = __FILE__;
  31. #endif
  32. /////////////////////////////////////////////////////////////////////////////
  33. // Local prototypes
  34. /////////////////////////////////////////////////////////////////////////////
  35. bool Is_Valid_ID_Char (char ch);
  36. /////////////////////////////////////////////////////////////////////////////
  37. //
  38. // EditStringDialogClass
  39. //
  40. /////////////////////////////////////////////////////////////////////////////
  41. EditStringDialogClass::EditStringDialogClass(CWnd* pParent /*=NULL*/)
  42. : m_Object (NULL),
  43. CDialog(EditStringDialogClass::IDD, pParent)
  44. {
  45. //{{AFX_DATA_INIT(EditStringDialogClass)
  46. // NOTE: the ClassWizard will add member initialization here
  47. //}}AFX_DATA_INIT
  48. return ;
  49. }
  50. /////////////////////////////////////////////////////////////////////////////
  51. //
  52. // DoDataExchange
  53. //
  54. /////////////////////////////////////////////////////////////////////////////
  55. void
  56. EditStringDialogClass::DoDataExchange (CDataExchange* pDX)
  57. {
  58. CDialog::DoDataExchange(pDX);
  59. //{{AFX_DATA_MAP(EditStringDialogClass)
  60. // NOTE: the ClassWizard will add DDX and DDV calls here
  61. //}}AFX_DATA_MAP
  62. return ;
  63. }
  64. BEGIN_MESSAGE_MAP(EditStringDialogClass, CDialog)
  65. //{{AFX_MSG_MAP(EditStringDialogClass)
  66. //}}AFX_MSG_MAP
  67. END_MESSAGE_MAP()
  68. /////////////////////////////////////////////////////////////////////////////
  69. //
  70. // OnInitDialog
  71. //
  72. /////////////////////////////////////////////////////////////////////////////
  73. BOOL
  74. EditStringDialogClass::OnInitDialog (void)
  75. {
  76. CDialog::OnInitDialog ();
  77. //
  78. // Get information about the location where we want to create the
  79. // sound preset picker control
  80. //
  81. HWND placeholder_wnd = ::GetDlgItem (m_hWnd, IDC_SOUND_PRESET_EDIT);
  82. CRect rect;
  83. ::GetWindowRect (placeholder_wnd, &rect);
  84. ScreenToClient (&rect);
  85. ::DestroyWindow (placeholder_wnd);
  86. //
  87. // Create the preset picker control
  88. //
  89. m_PresetPicker.Create_Picker (WS_CHILD | WS_TABSTOP | WS_VISIBLE, rect, this, 101);
  90. m_PresetPicker.Set_Read_Only (true);
  91. //
  92. // Configure the preset picker control
  93. //
  94. m_PresetPicker.Set_Class_ID (CLASSID_SOUND);
  95. if (m_Object != NULL && m_Object->Get_Sound_ID () > 0) {
  96. PresetClass *preset = PresetMgrClass::Find_Preset (m_Object->Get_Sound_ID ());
  97. m_PresetPicker.Set_Preset (preset);
  98. }
  99. //
  100. // Fill in the text controls
  101. //
  102. if (m_Object != NULL) {
  103. CString text = m_Object->Get_English_String ();
  104. Convert_Newline_To_Chars (text);
  105. SetDlgItemText (IDC_CODEID_EDIT, m_Object->Get_ID_Desc ());
  106. SetDlgItemText (IDC_STRING_EDIT, text);
  107. SetDlgItemText (IDC_ANIMATION_NAME_EDIT, m_Object->Get_Animation_Name ());
  108. //
  109. // Select the string so the user can readily modify its contents
  110. //
  111. ::SetFocus (::GetDlgItem (m_hWnd, IDC_STRING_EDIT));
  112. SendDlgItemMessage (IDC_STRING_EDIT, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
  113. } else {
  114. SetDlgItemText (IDC_CODEID_EDIT, "IDS_");
  115. //
  116. // Select the CODE ID so the user can enter a valid ID
  117. //
  118. ::SetFocus (::GetDlgItem (m_hWnd, IDC_CODEID_EDIT));
  119. SendDlgItemMessage (IDC_CODEID_EDIT, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
  120. }
  121. return FALSE;
  122. }
  123. /////////////////////////////////////////////////////////////////////////////
  124. //
  125. // Convert_Newline_To_Chars
  126. //
  127. /////////////////////////////////////////////////////////////////////////////
  128. void
  129. EditStringDialogClass::Convert_Newline_To_Chars (CString &string)
  130. {
  131. CString retval;
  132. //
  133. // Take a guess as to how large to make the final string
  134. //
  135. int count = string.GetLength ();
  136. //
  137. // Copy characters between the strings
  138. //
  139. for (int index = 0; index < count; index ++) {
  140. if (string[index] == '\n') {
  141. retval += "\\n";
  142. } else if (string[index] == '\t') {
  143. retval += "\\t";
  144. } else {
  145. retval += string[index];
  146. }
  147. }
  148. string = retval;
  149. return ;
  150. }
  151. /////////////////////////////////////////////////////////////////////////////
  152. //
  153. // Convert_Chars_To_Newline
  154. //
  155. /////////////////////////////////////////////////////////////////////////////
  156. void
  157. EditStringDialogClass::Convert_Chars_To_Newline (CString &string)
  158. {
  159. CString retval;
  160. //
  161. // Take a guess as to how large to make the final string
  162. //
  163. int count = string.GetLength ();
  164. //retval.GetBufferSetLength (count);
  165. //
  166. // Copy characters between the strings
  167. //
  168. for (int index = 0; index < count; index ++) {
  169. if (index + 1 < count && string[index] == '\\' && string[index + 1] == 'n') {
  170. retval += '\n';
  171. index ++;
  172. } else if (index + 1 < count && string[index] == '\\' && string[index + 1] == 't') {
  173. retval += '\t';
  174. index ++;
  175. } else {
  176. retval += string[index];
  177. }
  178. }
  179. string = retval;
  180. return ;
  181. }
  182. /////////////////////////////////////////////////////////////////////////////
  183. //
  184. // OnOK
  185. //
  186. /////////////////////////////////////////////////////////////////////////////
  187. void
  188. EditStringDialogClass::OnOK (void)
  189. {
  190. if (Validate_ID ()) {
  191. //
  192. // Create a new translation object (if necessary)
  193. //
  194. if (m_Object == NULL) {
  195. m_Object = new TDBObjClass;
  196. }
  197. //
  198. // Read the strings the user entered
  199. //
  200. CString code_id;
  201. GetDlgItemText (IDC_CODEID_EDIT, code_id);
  202. CString text;
  203. GetDlgItemText (IDC_STRING_EDIT, text);
  204. Convert_Chars_To_Newline (text);
  205. CString anim_name;
  206. GetDlgItemText (IDC_ANIMATION_NAME_EDIT, anim_name);
  207. //
  208. // Pass the new strings onto the translation object
  209. //
  210. m_Object->Set_ID_Desc (code_id);
  211. m_Object->Set_English_String (text);
  212. m_Object->Set_Animation_Name (anim_name);
  213. //
  214. // Pass the sound preset ID onto the translation object
  215. //
  216. int sound_id = -1;
  217. PresetClass *sound_preset = m_PresetPicker.Get_Preset ();
  218. if (sound_preset != NULL) {
  219. sound_id = sound_preset->Get_ID ();
  220. }
  221. m_Object->Set_Sound_ID (sound_id);
  222. CDialog::OnOK ();
  223. }
  224. return ;
  225. }
  226. /////////////////////////////////////////////////////////////////////////////
  227. //
  228. // Validate_ID
  229. //
  230. /////////////////////////////////////////////////////////////////////////////
  231. bool
  232. EditStringDialogClass::Validate_ID (void)
  233. {
  234. bool retval = false;
  235. //
  236. // Get the string ID from the control
  237. //
  238. CString code_id;
  239. GetDlgItemText (IDC_CODEID_EDIT, code_id);
  240. //
  241. // Validate the ID
  242. //
  243. return Validate_String_ID (m_hWnd, code_id);
  244. }
  245. /////////////////////////////////////////////////////////////////////////////
  246. //
  247. // Validate_String_ID
  248. //
  249. /////////////////////////////////////////////////////////////////////////////
  250. bool
  251. Validate_String_ID (HWND wnd, const char *string_id)
  252. {
  253. bool retval = false;
  254. CString code_id = string_id;
  255. if (code_id.GetLength () == 0) {
  256. //
  257. // Warn the user they need to enter some ID
  258. //
  259. ::MessageBox (wnd, "Please enter a descriptive token for the code identifier.", "Invalid Code ID", MB_ICONERROR | MB_OK);
  260. } else if (code_id.GetLength () < 4) {
  261. //
  262. // Warn the user they should enter a descriptive name
  263. //
  264. ::MessageBox (wnd, "Code identifier is too short. Please enter a more descriptive token for the code identifier.", "Invalid Code ID", MB_ICONERROR | MB_OK);
  265. } else if (code_id[0] < 0x41 || code_id[0] > 0x7A || (code_id[0] >= 0x5B && code_id[0] <= 0x60)) {
  266. //
  267. // Warn the user the name must start with a character
  268. //
  269. ::MessageBox (wnd, "The code identifier must begin with a character (not a number), please enter a valid identifier.", "Invalid Code ID", MB_ICONERROR | MB_OK);
  270. } else {
  271. //
  272. // Check each character in the string to make sure its exceptable
  273. //
  274. int count = code_id.GetLength ();
  275. bool is_valid = true;
  276. for (int index = 1; is_valid && index < count; index ++) {
  277. is_valid &= Is_Valid_ID_Char (code_id[index]);
  278. }
  279. if (is_valid == false) {
  280. //
  281. // Warn the user that the code ID contains an illegal character
  282. //
  283. ::MessageBox (wnd, "The code identifier can only contain characters (a-z, A-Z), numbers (0-9), and the underscore character (_), please enter a valid identifier.", "Invalid Code ID", MB_ICONERROR | MB_OK);
  284. } else {
  285. retval = true;
  286. }
  287. }
  288. return retval;
  289. }
  290. /////////////////////////////////////////////////////////////////////////////
  291. //
  292. // Is_Valid_ID_Char
  293. //
  294. /////////////////////////////////////////////////////////////////////////////
  295. bool
  296. Is_Valid_ID_Char (char ch)
  297. {
  298. bool is_valid = false;
  299. //
  300. // The character if valid if its either a character, a number, or an underscore
  301. //
  302. is_valid |= (ch >= '0' && ch <= '9');
  303. is_valid |= (ch >= 'A' && ch <= 'Z');
  304. is_valid |= (ch >= 'a' && ch <= 'z');
  305. is_valid |= (ch == '_');
  306. return is_valid;
  307. }