KeyboardOptionsMenu.cpp 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162
  1. /*
  2. ** Command & Conquer Generals(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. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. // FILE: KeyboardOptionsMenu.cpp /////////////////////////////////////////////////////////
  24. //-----------------------------------------------------------------------------
  25. //
  26. // Electronic Arts Pacific.
  27. //
  28. // Confidential Information
  29. // Copyright (C) 2002 - All Rights Reserved
  30. //
  31. //-----------------------------------------------------------------------------
  32. //
  33. // Project: Command & Conquer: Generals
  34. //
  35. // File name: KeyboardOptionsMenu.cpp
  36. //
  37. // Created: Chris Brue, July 2002
  38. //
  39. // Desc: the Keyboard options window control
  40. //
  41. //-----------------------------------------------------------------------------
  42. ///////////////////////////////////////////////////////////////////////////////
  43. // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
  44. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  45. #include "Common/GameAudio.h"
  46. #include "Common/GameEngine.h"
  47. #include "Common/UserPreferences.h"
  48. #include "GameClient/WindowLayout.h"
  49. #include "GameClient/Gadget.h"
  50. #include "GameClient/GadgetCheckBox.h"
  51. #include "GameClient/GadgetComboBox.h"
  52. #include "GameClient/GadgetListBox.h"
  53. #include "GameClient/GadgetSlider.h"
  54. #include "GameClient/GadgetStaticText.h"
  55. #include "GameClient/IMEManager.h"
  56. #include "GameClient/Shell.h"
  57. #include "GameClient/KeyDefs.h"
  58. #include "GameClient/GameWindowManager.h"
  59. #include "GameClient/Mouse.h"
  60. #include "GameClient/GameText.h"
  61. #include "GameClient/MetaEvent.h"
  62. #include "GameNetwork/FirewallHelper.h"
  63. #include "GameNetwork/IPEnumeration.h"
  64. // PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
  65. WindowMsgHandledType KeyboardTextEntryInput( GameWindow *window, UnsignedInt msg,
  66. WindowMsgData mData1, WindowMsgData mData2 );
  67. static NameKeyType buttonBackID = NAMEKEY_INVALID;
  68. static GameWindow *buttonBack = NULL;
  69. static NameKeyType parentKeyboardOptionsMenuID = NAMEKEY_INVALID;
  70. static GameWindow *parentKeyboardOptionsMenu = NULL;
  71. static NameKeyType comboBoxCategoryListID = NAMEKEY_INVALID;
  72. static GameWindow *comboBoxCategoryList = NULL;
  73. static NameKeyType listBoxCommandListID = NAMEKEY_INVALID;
  74. static GameWindow *listBoxCommandList = NULL;
  75. static NameKeyType staticTextDescriptionID = NAMEKEY_INVALID;
  76. static GameWindow *staticTextDescription = NULL;
  77. static NameKeyType staticTextCurrentHotkeyID = NAMEKEY_INVALID;
  78. static GameWindow *staticTextCurrentHotkey = NULL;
  79. static NameKeyType buttonResetAllID = NAMEKEY_INVALID;
  80. static GameWindow *buttonResetAll = NULL;
  81. static NameKeyType textEntryAssignHotkeyID = NAMEKEY_INVALID;
  82. static GameWindow *textEntryAssignHotkey = NULL;
  83. static NameKeyType buttonAssignID = NAMEKEY_INVALID;
  84. static GameWindow *buttonAssign = NULL;
  85. //use Bools to test if modifiers are used
  86. Bool shiftDown = false;
  87. Bool altDown = false;
  88. Bool ctrlDown = false;
  89. // shows whether or not a correctly formatted hotkey assignment is in the text area
  90. Bool absolute = false;
  91. // initialize these, they will be used a lot
  92. UnicodeString alt;
  93. UnicodeString ctrl;
  94. UnicodeString shift;
  95. void populateCategoryBox()
  96. {
  97. Int i;
  98. Int index;
  99. Color color = GameMakeColor(255,255,255,255);
  100. AsciiString temp;
  101. UnicodeString str;
  102. GadgetComboBoxReset(comboBoxCategoryList);
  103. for ( i = 0; i < CATEGORY_NUM_CATEGORIES; ++i)
  104. {
  105. temp.format("GUI:%s", CategoryListName[i]);
  106. str = TheGameText->fetch( temp );
  107. index = GadgetComboBoxAddEntry(comboBoxCategoryList, str, color);
  108. }
  109. GadgetComboBoxSetSelectedPos(comboBoxCategoryList, 0);
  110. }
  111. // keeps track of whether or not each text modifier is being currently displayed in the text entry field
  112. void setKeyDown( UnicodeString mod, Bool b )
  113. {
  114. if( mod == TheGameText->fetch( "KEYBOARD:Shift+" ) )
  115. shiftDown = b;
  116. else if( mod == TheGameText->fetch( "KEYBOARD:Ctrl+" ) )
  117. ctrlDown = b;
  118. else
  119. altDown = b;
  120. }
  121. // initialized the command list box
  122. void fillCommandListBox( MappableKeyCategories cat )
  123. {
  124. if(!listBoxCommandList)
  125. return;
  126. GadgetListBoxReset(listBoxCommandList);
  127. Color color = GameMakeColor(255,255,255,255);
  128. for(const MetaMapRec *rec = TheMetaMap->getFirstMetaMapRec(); rec; rec = rec->m_next)
  129. {
  130. if(rec->m_category == cat)
  131. GadgetListBoxAddEntryText(listBoxCommandList, rec->m_displayName, color, -1, -1 );
  132. }
  133. }
  134. void doKeyUp(EntryData *e, UnicodeString mod )
  135. {
  136. char c = e->text->getText().getCharAt( e->text->getTextLength() - 1);
  137. // if there are modifiers, check which ones exist and act accordingly
  138. if( c == '+' )
  139. {
  140. // if all of the mods are down, make string out of other two
  141. if( altDown && ctrlDown && shiftDown )
  142. {
  143. if( mod == shift )
  144. {
  145. UnicodeString temp = alt;
  146. temp.concat( ctrl );
  147. e->text->setText( temp );
  148. e->charPos = e->text->getTextLength();
  149. setKeyDown( mod, false );
  150. }
  151. else if( mod == alt )
  152. {
  153. UnicodeString temp = ctrl;
  154. temp.concat( shift );
  155. e->text->setText( temp );
  156. e->charPos = e->text->getTextLength();
  157. setKeyDown( mod, false );
  158. }
  159. else if( mod == ctrl )
  160. {
  161. UnicodeString temp = alt;
  162. temp.concat( shift );
  163. e->text->setText( temp );
  164. e->charPos = e->text->getTextLength();
  165. setKeyDown( mod, false );
  166. }
  167. }
  168. // if alt and ctrl are both down
  169. else if( altDown && ctrlDown )
  170. {
  171. if( mod == alt )
  172. {
  173. e->text->setText( ctrl );
  174. e->charPos = e->text->getTextLength();
  175. setKeyDown( mod, false );
  176. }
  177. else if( mod == ctrl )
  178. {
  179. e->text->setText( ctrl );
  180. e->charPos = e->text->getTextLength();
  181. setKeyDown( mod, false );
  182. }
  183. }
  184. // if alt and shift are both down
  185. else if( altDown && shiftDown )
  186. {
  187. if( mod == alt )
  188. {
  189. e->text->setText( shift );
  190. e->charPos = e->text->getTextLength();
  191. setKeyDown( mod, false );
  192. }
  193. else if( mod == shift )
  194. {
  195. e->text->setText( alt );
  196. e->charPos = e->text->getTextLength();
  197. setKeyDown( mod, false );
  198. }
  199. }
  200. // if ctrl and shift are both down
  201. else if( ctrlDown && shiftDown )
  202. {
  203. if( mod == ctrl )
  204. {
  205. e->text->setText( shift );
  206. e->charPos = e->text->getTextLength();
  207. setKeyDown( mod, false );
  208. }
  209. else if( mod == shift )
  210. {
  211. e->text->setText( ctrl );
  212. e->charPos = e->text->getTextLength();
  213. setKeyDown( mod, false );
  214. }
  215. }
  216. // else only one mod, just clear everything
  217. else
  218. {
  219. e->text->setText( UnicodeString::TheEmptyString );
  220. e->sText->setText( UnicodeString::TheEmptyString );
  221. e->charPos = e->text->getTextLength();
  222. setKeyDown( mod, false );
  223. }
  224. }
  225. else
  226. {
  227. // this absolute thang will/might need more than one test
  228. absolute = true;
  229. }
  230. }
  231. // preforms the correct action when a modifier key is pressed down
  232. void doKeyDown(EntryData *e, UnicodeString mod )
  233. {
  234. // simple cases if there are no mods present
  235. //sanity check
  236. if( e->text->getTextLength() <= 1 )
  237. {
  238. // reset text
  239. e->text->setText( mod );
  240. e->sText->setText( mod );
  241. e->charPos = e->text->getTextLength();
  242. setKeyDown( mod, true );
  243. }
  244. else //if( e->text->getTextLength() )
  245. {
  246. char c = e->text->getText().getCharAt( e->text->getTextLength() - 1);
  247. if( c != '+' && absolute)
  248. {
  249. e->text->setText( mod );
  250. e->sText->setText( mod );
  251. e->charPos = e->text->getTextLength();
  252. // try reseting all mods first
  253. setKeyDown( shift, false );
  254. setKeyDown( alt, false );
  255. setKeyDown( ctrl, false );
  256. setKeyDown( mod, true );
  257. absolute = false;
  258. }
  259. //else only allow modifiers are present
  260. else
  261. {
  262. if( mod == shift && shiftDown )
  263. {
  264. }
  265. else if( mod == ctrl && ctrlDown )
  266. {
  267. }
  268. else if( mod == alt && altDown )
  269. {
  270. }
  271. else
  272. {
  273. //figure out the cases for which mod goes first
  274. // puts shift at the end of the mods
  275. if( altDown && ctrlDown)
  276. {
  277. UnicodeString temp = alt;
  278. temp.concat( ctrl );
  279. temp.concat( mod );
  280. e->text->setText(temp);
  281. e->charPos = e->text->getTextLength();
  282. setKeyDown( mod, true );
  283. }
  284. // if alt and shift are down, puts ctrl in the middle
  285. else if( altDown && shiftDown )
  286. {
  287. UnicodeString temp = alt;
  288. temp.concat( ctrl );
  289. temp.concat( shift );
  290. e->text->setText( temp );
  291. e->charPos = e->text->getTextLength();
  292. setKeyDown( mod, true );
  293. }
  294. // puts either shift or ctrl after alt
  295. else if( altDown )
  296. {
  297. UnicodeString temp = alt;
  298. temp.concat( mod );
  299. e->text->setText(temp);
  300. e->charPos = e->text->getTextLength();
  301. setKeyDown( mod, true );
  302. }
  303. // puts alt infront of these two
  304. else if( ctrlDown && shiftDown )
  305. {
  306. UnicodeString temp = alt;
  307. temp.concat( ctrl );
  308. temp.concat( shift );
  309. e->text->setText( temp );
  310. e->charPos = e->text->getTextLength();
  311. setKeyDown( mod, true );
  312. }
  313. // if only ctrl+ is currently being displayed
  314. else if( ctrlDown )
  315. {
  316. // if it's alt, put it in front
  317. if( mod == alt )
  318. {
  319. UnicodeString temp = mod;
  320. temp.concat( ctrl );
  321. e->text->setText( temp );
  322. e->charPos = e->text->getTextLength();
  323. setKeyDown( mod, true );
  324. }
  325. //else put shift after ctrl
  326. else
  327. {
  328. UnicodeString temp = ctrl;
  329. temp.concat( mod );
  330. e->text->setText( temp );
  331. e->charPos = e->text->getTextLength();
  332. setKeyDown( mod, true );
  333. }
  334. }
  335. // else put alt or ctrl in front of shift
  336. else if( shiftDown )
  337. {
  338. UnicodeString temp = mod;
  339. temp.concat( shift );
  340. e->text->setText( temp );
  341. e->charPos = e->text->getTextLength();
  342. setKeyDown( mod, true );
  343. }
  344. }
  345. }
  346. }
  347. }
  348. //-------------------------------------------------------------------------------------------------
  349. /** Initialize the options menu */
  350. //-------------------------------------------------------------------------------------------------
  351. void KeyboardOptionsMenuInit( WindowLayout *layout, void *userData )
  352. {
  353. //set keyboard focus to main parent
  354. parentKeyboardOptionsMenuID = TheNameKeyGenerator->nameToKey("KeyboardOptionsMenu.wnd:ParentKeyboardOptionsMenu");
  355. parentKeyboardOptionsMenu = TheWindowManager->winGetWindowFromId( NULL, parentKeyboardOptionsMenuID );
  356. // get ids for our children controls
  357. buttonBackID = TheNameKeyGenerator->nameToKey( AsciiString("KeyboardOptionsMenu.wnd:ButtonBack") );
  358. buttonBack = TheWindowManager->winGetWindowFromId( parentKeyboardOptionsMenu, buttonBackID );
  359. comboBoxCategoryListID = TheNameKeyGenerator->nameToKey( "KeyboardOptionsMenu.wnd:ComboBoxCategoryList" );
  360. comboBoxCategoryList = TheWindowManager->winGetWindowFromId( /*parentKeyboardOptionsMenu*/NULL, comboBoxCategoryListID );
  361. listBoxCommandListID = TheNameKeyGenerator->nameToKey( "KeyboardOptionsMenu.wnd:ListBoxCommandList" );
  362. listBoxCommandList = TheWindowManager->winGetWindowFromId( NULL, listBoxCommandListID );
  363. staticTextDescriptionID = TheNameKeyGenerator->nameToKey( "KeyboardOptionsMenu.wnd:StaticTextDescription" );
  364. staticTextDescription = TheWindowManager->winGetWindowFromId( NULL, staticTextDescriptionID );
  365. staticTextCurrentHotkeyID = TheNameKeyGenerator->nameToKey( "KeyboardOptionsMenu.wnd:StaticTextCurrentHotkey" );
  366. staticTextCurrentHotkey = TheWindowManager->winGetWindowFromId( NULL, staticTextCurrentHotkeyID );
  367. buttonResetAllID = TheNameKeyGenerator->nameToKey( "KeyboardOptionsMenu.wnd:ButtonResetAll" );
  368. buttonResetAll = TheWindowManager->winGetWindowFromId( NULL, buttonResetAllID );
  369. textEntryAssignHotkeyID = TheNameKeyGenerator->nameToKey( "KeyboardOptionsMenu.wnd:TextEntryAssignHotkey" );
  370. textEntryAssignHotkey = TheWindowManager->winGetWindowFromId( NULL, textEntryAssignHotkeyID );
  371. buttonAssignID = TheNameKeyGenerator->nameToKey( "KeyboardOptionsMenu.wnd:ButtonAssign" );
  372. buttonAssign = TheWindowManager->winGetWindowFromId( NULL, buttonAssignID );
  373. //special text entry box that needs its own function
  374. textEntryAssignHotkey->winSetInputFunc( KeyboardTextEntryInput );
  375. // populate category combo box
  376. populateCategoryBox();
  377. // populate command list
  378. fillCommandListBox(CATEGORY_CONTROL);
  379. //disable textEntry until specific command is chosen
  380. textEntryAssignHotkey->winEnable( false );
  381. //clear textEntry field
  382. EntryData *e = (EntryData *)textEntryAssignHotkey->winGetUserData();
  383. e->text->setText( UnicodeString::TheEmptyString );
  384. e->charPos = e->text->getTextLength();
  385. // set up these strings because they will be called a lot
  386. alt = TheGameText->fetch( "KEYBOARD:Alt+" );
  387. ctrl = TheGameText->fetch( "KEYBOARD:Ctrl+" );
  388. shift = TheGameText->fetch( "KEYBOARD:Shift+" );
  389. // show menu
  390. layout->hide( FALSE );
  391. // set keyboard focus to main parent
  392. TheWindowManager->winSetFocus( parentKeyboardOptionsMenu );
  393. }
  394. //-------------------------------------------------------------------------------------------------
  395. /** options menu shutdown method */
  396. //-------------------------------------------------------------------------------------------------
  397. void KeyboardOptionsMenuShutdown( WindowLayout *layout, void *userData )
  398. {
  399. // hide menu
  400. layout->hide( TRUE );
  401. // our shutdown is complete
  402. TheShell->shutdownComplete( layout );
  403. }
  404. //-------------------------------------------------------------------------------------------------
  405. /** options menu update method */
  406. //-------------------------------------------------------------------------------------------------
  407. void KeyboardOptionsMenuUpdate( WindowLayout *layout, void *userData )
  408. {
  409. } // end OptionsMenuUpdate
  410. //-------------------------------------------------------------------------------------------------
  411. /** Options menu input callback */
  412. //-------------------------------------------------------------------------------------------------
  413. WindowMsgHandledType KeyboardOptionsMenuInput( GameWindow *window, UnsignedInt msg,
  414. WindowMsgData mData1, WindowMsgData mData2 )
  415. {
  416. switch( msg )
  417. {
  418. // --------------------------------------------------------------------------------------------
  419. case GWM_CHAR:
  420. {
  421. UnsignedByte key = mData1;
  422. UnsignedByte state = mData2;
  423. switch( key )
  424. {
  425. // ----------------------------------------------------------------------------------------
  426. case KEY_ESC:
  427. {
  428. //
  429. // send a simulated selected event to the parent window of the
  430. // back/exit button
  431. //
  432. if( BitTest( state, KEY_STATE_UP ) )
  433. {
  434. AsciiString buttonName( "KeyboardOptionsMenu.wnd:ButtonBack" );
  435. NameKeyType buttonID = TheNameKeyGenerator->nameToKey( buttonName );
  436. GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonID );
  437. TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
  438. (WindowMsgData)button, buttonID );
  439. } // end if
  440. // don't let key fall through anywhere else
  441. return MSG_HANDLED;
  442. } // end escape
  443. } // end switch( key )
  444. } // end char
  445. } // end switch( msg )
  446. return MSG_IGNORED;
  447. } // end KeyboardOptionsMenuInput
  448. //-------------------------------------------------------------------------------------------------
  449. /** options menu window system callback */
  450. //-------------------------------------------------------------------------------------------------
  451. WindowMsgHandledType KeyboardOptionsMenuSystem( GameWindow *window, UnsignedInt msg,
  452. WindowMsgData mData1, WindowMsgData mData2 )
  453. {
  454. switch( msg )
  455. {
  456. // --------------------------------------------------------------------------------------------
  457. case GWM_CREATE:
  458. {
  459. break;
  460. } // end create
  461. //---------------------------------------------------------------------------------------------
  462. case GWM_DESTROY:
  463. {
  464. break;
  465. } // end case
  466. // --------------------------------------------------------------------------------------------
  467. case GWM_INPUT_FOCUS:
  468. {
  469. // if we're givin the opportunity to take the keyboard focus we must say we want it
  470. if( mData1 == TRUE )
  471. *(Bool *)mData2 = TRUE;
  472. return MSG_HANDLED;
  473. } // end input
  474. //---------------------------------------------------------------------------------------------
  475. case GCM_SELECTED:
  476. {
  477. GameWindow *control = (GameWindow *)mData1;
  478. Int controlID = control->winGetWindowId();
  479. if(controlID == comboBoxCategoryListID )
  480. {
  481. Int selected;
  482. GadgetComboBoxGetSelectedPos(comboBoxCategoryList, &selected);
  483. LookupListRec rec;
  484. rec = CategoryListName[selected];
  485. MappableKeyCategories cat = (MappableKeyCategories)(rec.value);
  486. fillCommandListBox( cat );
  487. //reset current hotkey description
  488. GadgetStaticTextSetText( staticTextDescription, TheGameText->fetch( "GUI:NULL" ) );
  489. //reset current hotkey text
  490. GadgetStaticTextSetText( staticTextCurrentHotkey, TheGameText->fetch( "GUI:NULL" ) );
  491. //clear textEntry field
  492. EntryData *e = (EntryData *)textEntryAssignHotkey->winGetUserData();
  493. e->text->setText( UnicodeString::TheEmptyString );
  494. e->charPos = e->text->getTextLength();
  495. //disable textEntry until specific command is chosen
  496. textEntryAssignHotkey->winEnable( false );
  497. }
  498. break;
  499. } // end selected
  500. // ---------------------------------------------------------------------------------------------
  501. case GLM_SELECTED:
  502. {
  503. GameWindow *control = (GameWindow *)mData1;
  504. Int controlID = control->winGetWindowId();
  505. if( controlID == listBoxCommandListID )
  506. {
  507. Int selected;
  508. GadgetListBoxGetSelected( listBoxCommandList, &selected );
  509. UnicodeString str;
  510. str = GadgetListBoxGetText( listBoxCommandList, selected/*, Int column = 0*/ );
  511. for(const MetaMapRec *rec = TheMetaMap->getFirstMetaMapRec(); rec; rec = rec->m_next)
  512. {
  513. if(rec->m_displayName == str)
  514. {
  515. //set text in description window
  516. GadgetStaticTextSetText( staticTextDescription, rec->m_description );
  517. //set text in current hotkey text
  518. MappableKeyType type = rec->m_key;
  519. //enable text entry for assigning different hotkey
  520. textEntryAssignHotkey->winEnable( true );
  521. for (const LookupListRec* keyName = KeyNames; keyName->name; keyName++)
  522. {
  523. if( keyName->value == type )
  524. {
  525. const char *cptr = keyName->name;
  526. AsciiString aStr;
  527. aStr.format( cptr );
  528. UnicodeString uStr;
  529. uStr.translate( aStr );
  530. GadgetStaticTextSetText( staticTextCurrentHotkey, uStr );
  531. break;
  532. }
  533. }
  534. break;
  535. }
  536. } // end if
  537. } // end selected
  538. break;
  539. } // end case
  540. // ---------------------------------------------------------------------------------------------
  541. case GBM_SELECTED:
  542. {
  543. GameWindow *control = (GameWindow *)mData1;
  544. Int controlID = control->winGetWindowId();
  545. if( controlID == buttonBackID )
  546. {
  547. // go back one screen
  548. TheShell->pop();
  549. } // end if
  550. else if( controlID == buttonAssignID )
  551. {
  552. // check grammar in text field
  553. }
  554. else if( controlID == buttonResetAllID )
  555. {
  556. // populate category combo box
  557. populateCategoryBox();
  558. // populate command list
  559. fillCommandListBox(CATEGORY_CONTROL);
  560. //reset current hotkey text
  561. GadgetStaticTextSetText( staticTextCurrentHotkey, TheGameText->fetch( "GUI:NULL" ) );
  562. //clear textEntry field
  563. EntryData *e = (EntryData *)textEntryAssignHotkey->winGetUserData();
  564. e->text->setText( UnicodeString::TheEmptyString );
  565. e->charPos = e->text->getTextLength();
  566. //set all mods to false
  567. setKeyDown(alt, false );
  568. setKeyDown(ctrl, false );
  569. setKeyDown(shift, false );
  570. //disable text entry
  571. textEntryAssignHotkey->winEnable( false );
  572. }
  573. break;
  574. } // end selected
  575. default:
  576. return MSG_IGNORED;
  577. } // end switch
  578. return MSG_HANDLED;
  579. } // end KeyboardOptionsMenuSystem
  580. // KeyboardTextEntryInput =======================================================
  581. /** Handle input for text entry field */
  582. //=============================================================================
  583. WindowMsgHandledType KeyboardTextEntryInput( GameWindow *window, UnsignedInt msg,
  584. WindowMsgData mData1, WindowMsgData mData2 )
  585. {
  586. EntryData *e = (EntryData *)window->winGetUserData();
  587. WinInstanceData *instData = window->winGetInstanceData();
  588. if ( TheIMEManager && TheIMEManager->isAttachedTo( window) && TheIMEManager->isComposing())
  589. {
  590. // ignore input while IME has focus
  591. return MSG_HANDLED;
  592. }
  593. switch( msg )
  594. {
  595. // ------------------------------------------------------------------------
  596. case GWM_IME_CHAR:
  597. {
  598. WideChar ch = (WideChar) mData1;
  599. // --------------------------------------------------------------------
  600. if ( ch == VK_RETURN )
  601. {
  602. // Done with this edit
  603. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  604. GEM_EDIT_DONE,
  605. (WindowMsgData)window,
  606. 0 );
  607. return MSG_HANDLED;
  608. };
  609. if( ch )
  610. {
  611. // Constrain keys based on rules for entry box.
  612. if( e->numericalOnly )
  613. {
  614. if( TheWindowManager->winIsDigit( ch ) == 0 )
  615. return MSG_HANDLED;
  616. }
  617. else if( e->alphaNumericalOnly )
  618. {
  619. if( TheWindowManager->winIsAlNum( ch ) == 0 )
  620. return MSG_HANDLED;
  621. }
  622. else if ( e->aSCIIOnly )
  623. {
  624. if ( TheWindowManager->winIsAscii( ch ) == 0 )
  625. {
  626. return MSG_HANDLED;
  627. }
  628. }
  629. if( e->text->getTextLength() <= 1 )
  630. {
  631. e->text->setText( UnicodeString::TheEmptyString );
  632. e->text->appendChar( ch );
  633. e->charPos = e->text->getTextLength();
  634. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  635. GEM_UPDATE_TEXT,
  636. (WindowMsgData)window,
  637. 0 );
  638. return MSG_HANDLED;
  639. }
  640. //else check is modifiers are persent
  641. else
  642. {
  643. char c = e->text->getText().getCharAt(e->text->getTextLength() - 1 );
  644. if(c == '+' )
  645. {
  646. e->text->appendChar( ch );
  647. e->charPos++;
  648. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  649. GEM_UPDATE_TEXT,
  650. (WindowMsgData)window,
  651. 0 );
  652. return MSG_HANDLED;
  653. }
  654. // if not, reset textEntry
  655. else
  656. {
  657. //if any of the modifiers are down, just replace letter
  658. if( ( shiftDown | ctrlDown | altDown ) && ( !absolute ) )
  659. {
  660. char test = e->text->getText().getCharAt(e->text->getTextLength() - 1);
  661. // only replace letter if not the same as last char of string (removes flickering)
  662. if( test != ch )
  663. {
  664. e->text->removeLastChar();
  665. e->text->appendChar( ch );
  666. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  667. GEM_UPDATE_TEXT,
  668. (WindowMsgData)window,
  669. 0 );
  670. }
  671. }
  672. //else reset textEntry
  673. else
  674. {
  675. e->text->setText( UnicodeString::TheEmptyString );
  676. e->text->appendChar( ch );
  677. e->charPos = 1;
  678. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  679. GEM_UPDATE_TEXT,
  680. (WindowMsgData)window,
  681. 0 );
  682. }
  683. return MSG_HANDLED;
  684. }
  685. }
  686. }
  687. break;
  688. }
  689. // ------------------------------------------------------------------------
  690. case GWM_CHAR:
  691. switch( mData1 )
  692. {
  693. /*
  694. // --------------------------------------------------------------------
  695. case KEY_KPENTER:
  696. case KEY_ENTER:
  697. // Done with this edit
  698. if( BitTest( mData2, KEY_STATE_DOWN ) )
  699. {
  700. if( e->receivedUnichar == FALSE )
  701. {
  702. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  703. GEM_EDIT_DONE,
  704. (WindowMsgData)window,
  705. 0 );
  706. }
  707. }
  708. break;
  709. */
  710. // -------------------------------------------------------------------------------------------
  711. // modifier cases
  712. case KEY_LCTRL:
  713. {
  714. if( BitTest( mData2, KEY_STATE_DOWN ) )
  715. {
  716. UnicodeString mod = ctrl;
  717. doKeyDown( e, mod );
  718. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  719. GEM_UPDATE_TEXT,
  720. (WindowMsgData)window,
  721. 0 );
  722. return MSG_HANDLED;
  723. }
  724. if( BitTest(mData2, KEY_STATE_UP ) )
  725. {
  726. UnicodeString mod = ctrl;
  727. doKeyUp( e, mod );
  728. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  729. GEM_UPDATE_TEXT,
  730. (WindowMsgData)window,
  731. 0 );
  732. return MSG_HANDLED;
  733. }
  734. break;
  735. }
  736. case KEY_RSHIFT:
  737. case KEY_LSHIFT:
  738. {
  739. if( BitTest( mData2, KEY_STATE_DOWN ) )
  740. {
  741. UnicodeString mod = shift;
  742. doKeyDown( e, mod );
  743. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  744. GEM_UPDATE_TEXT,
  745. (WindowMsgData)window,
  746. 0 );
  747. return MSG_HANDLED;
  748. }
  749. if( BitTest( mData2, KEY_STATE_UP ) )
  750. {
  751. UnicodeString mod = shift;
  752. doKeyUp(e, mod );
  753. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  754. GEM_UPDATE_TEXT,
  755. (WindowMsgData)window,
  756. 0 );
  757. return MSG_HANDLED;
  758. }
  759. break;
  760. }
  761. case KEY_LALT:
  762. {
  763. if( BitTest( mData2, KEY_STATE_DOWN ) )
  764. {
  765. UnicodeString mod = alt;
  766. doKeyDown( e, mod );
  767. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  768. GEM_UPDATE_TEXT,
  769. (WindowMsgData)window,
  770. 0 );
  771. return MSG_HANDLED;
  772. }
  773. if( BitTest(mData2, KEY_STATE_UP ) )
  774. {
  775. UnicodeString mod = alt;
  776. doKeyUp( e, mod );
  777. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  778. GEM_UPDATE_TEXT,
  779. (WindowMsgData)window,
  780. 0 );
  781. return MSG_HANDLED;
  782. }
  783. break;
  784. }
  785. // -------------------------------------------------------------------------------------------
  786. // --------------------------------------------------------------------
  787. // Don't process these keys
  788. case KEY_ESC:
  789. case KEY_PGUP:
  790. case KEY_PGDN:
  791. case KEY_HOME:
  792. case KEY_END:
  793. case KEY_F1:
  794. case KEY_F2:
  795. case KEY_F3:
  796. case KEY_F4:
  797. case KEY_F5:
  798. case KEY_F6:
  799. case KEY_F7:
  800. case KEY_F8:
  801. case KEY_F9:
  802. case KEY_F10:
  803. case KEY_F11:
  804. case KEY_F12:
  805. case KEY_CAPS:
  806. return MSG_IGNORED;
  807. // --------------------------------------------------------------------
  808. case KEY_DOWN:
  809. case KEY_RIGHT:
  810. case KEY_TAB:
  811. if( BitTest( mData2, KEY_STATE_DOWN ) )
  812. window->winNextTab();
  813. break;
  814. // --------------------------------------------------------------------
  815. case KEY_UP:
  816. case KEY_LEFT:
  817. if( BitTest( mData2, KEY_STATE_DOWN ) )
  818. window->winPrevTab();
  819. break;
  820. // --------------------------------------------------------------------
  821. case KEY_BACKSPACE:
  822. {
  823. e->text->setText( UnicodeString::TheEmptyString );
  824. e->charPos = e->text->getTextLength();
  825. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  826. GEM_UPDATE_TEXT,
  827. (WindowMsgData)window,
  828. 0 );
  829. setKeyDown(shift, false );
  830. setKeyDown(ctrl, false );
  831. setKeyDown(alt, false );
  832. return MSG_HANDLED;
  833. break;
  834. }
  835. case KEY_DEL:
  836. {
  837. if( BitTest( mData2, KEY_STATE_DOWN ) )
  838. {
  839. // if conCharPos != 0 this will fall through to next case.
  840. // it should be noted that conCharPos can only != 0 in Jap & Kor
  841. if( e->conCharPos == 0 )
  842. {
  843. if( e->charPos > 0 )
  844. {
  845. e->text->removeLastChar();
  846. e->sText->removeLastChar();
  847. e->charPos--;
  848. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  849. GEM_UPDATE_TEXT,
  850. (WindowMsgData)window,
  851. 0 );
  852. } // end if
  853. }
  854. }
  855. break;
  856. }
  857. // ----------------------------------------------------------------------------------------
  858. // doing research to see if this will fix the keyboard stuff
  859. /*default:
  860. {
  861. char ch = mData1;
  862. if( ch && ( BitTest( mData2, KEY_STATE_DOWN ) ) )
  863. {
  864. // Constrain keys based on rules for entry box.
  865. if( e->numericalOnly )
  866. {
  867. if( TheWindowManager->winIsDigit( ch ) == 0 )
  868. return MSG_HANDLED;
  869. }
  870. else if( e->alphaNumericalOnly )
  871. {
  872. if( TheWindowManager->winIsAlNum( ch ) == 0 )
  873. return MSG_HANDLED;
  874. }
  875. else if ( e->aSCIIOnly )
  876. {
  877. if ( TheWindowManager->winIsAscii( ch ) == 0 )
  878. {
  879. return MSG_HANDLED;
  880. }
  881. }
  882. if( e->text->getTextLength() <= 1 )
  883. {
  884. e->text->setText( UnicodeString::TheEmptyString );
  885. e->text->appendChar( ch );
  886. e->charPos = e->text->getTextLength();
  887. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  888. GEM_UPDATE_TEXT,
  889. (WindowMsgData)window,
  890. 0 );
  891. return MSG_HANDLED;
  892. }
  893. //else check is modifiers are persent
  894. else
  895. {
  896. char c = e->text->getText().getCharAt(e->text->getTextLength() - 1 );
  897. if(c == '+' )
  898. {
  899. e->text->appendChar( ch );
  900. e->charPos++;
  901. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  902. GEM_UPDATE_TEXT,
  903. (WindowMsgData)window,
  904. 0 );
  905. return MSG_HANDLED;
  906. }
  907. // if not, reset textEntry
  908. else
  909. {
  910. //if any of the modifiers are down, just replace letter
  911. if( ( shiftDown | ctrlDown | altDown ) && ( !absolute ) )
  912. {
  913. char test = e->text->getText().getCharAt(e->text->getTextLength() - 1);
  914. // only replace letter if not the same as last char of string (removes flickering)
  915. if( test != ch )
  916. {
  917. e->text->removeLastChar();
  918. e->text->appendChar( ch );
  919. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  920. GEM_UPDATE_TEXT,
  921. (WindowMsgData)window,
  922. 0 );
  923. }
  924. }
  925. //else reset textEntry
  926. else
  927. {
  928. e->text->setText( UnicodeString::TheEmptyString );
  929. e->text->appendChar( ch );
  930. e->charPos = 1;
  931. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  932. GEM_UPDATE_TEXT,
  933. (WindowMsgData)window,
  934. 0 );
  935. }
  936. return MSG_HANDLED;
  937. }
  938. }
  939. }
  940. }*/
  941. } // end switch( mData1 )
  942. break;
  943. // ------------------------------------------------------------------------
  944. case GWM_LEFT_DOWN:
  945. BitSet( instData->m_state, WIN_STATE_HILITED );
  946. TheWindowManager->winSetFocus( window );
  947. break;
  948. // ------------------------------------------------------------------------
  949. case GWM_MOUSE_ENTERING:
  950. if (BitTest( instData->getStyle(), GWS_MOUSE_TRACK ) )
  951. {
  952. BitSet( instData->m_state, WIN_STATE_HILITED );
  953. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  954. GBM_MOUSE_ENTERING,
  955. (WindowMsgData)window, 0 );
  956. TheWindowManager->winSetFocus( window );
  957. }
  958. break;
  959. // ------------------------------------------------------------------------
  960. case GWM_MOUSE_LEAVING:
  961. if( BitTest( instData->getStyle(), GWS_MOUSE_TRACK ) )
  962. {
  963. BitClear( instData->m_state, WIN_STATE_HILITED );
  964. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  965. GBM_MOUSE_LEAVING,
  966. (WindowMsgData)window, 0 );
  967. }
  968. break;
  969. // ------------------------------------------------------------------------
  970. case GWM_LEFT_DRAG:
  971. if( BitTest( instData->getStyle(), GWS_MOUSE_TRACK ) )
  972. TheWindowManager->winSendSystemMsg( window->winGetOwner(),
  973. GGM_LEFT_DRAG,
  974. (WindowMsgData)window, 0 );
  975. break;
  976. // ------------------------------------------------------------------------
  977. default:
  978. return MSG_IGNORED;
  979. } // end switch( msg )
  980. return MSG_HANDLED;
  981. } // end GadgetTextEntryInput