diff --git a/src/game/client/gui/gadget/gadgetcheckbox.cpp b/src/game/client/gui/gadget/gadgetcheckbox.cpp index e08e12a0c..5c787e58a 100644 --- a/src/game/client/gui/gadget/gadgetcheckbox.cpp +++ b/src/game/client/gui/gadget/gadgetcheckbox.cpp @@ -14,6 +14,139 @@ */ #include "gadgetcheckbox.h" #include "gamewindowmanager.h" +#include "keyboard.h" + +WindowMsgHandledType Gadget_Check_Box_Input( + GameWindow *check_box, unsigned int message, unsigned int data_1, unsigned int data_2) +{ + WinInstanceData *instance_data = check_box->Win_Get_Instance_Data(); + + switch (message) { + case GWM_LEFT_DOWN: + case GWM_RIGHT_DOWN: + return MSG_HANDLED; + case GWM_LEFT_UP: + if ((instance_data->Get_State() & 2) == 0) { + return MSG_IGNORED; + } + + instance_data->m_state ^= 4; +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + check_box->Win_Get_Owner(), GBM_SELECTED, reinterpret_cast(check_box), data_1); +#endif + return MSG_HANDLED; + case GWM_LEFT_DRAG: +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + check_box->Win_Get_Owner(), GBM_SELECTED, reinterpret_cast(check_box), data_1); +#endif + return MSG_HANDLED; + case GWM_RIGHT_UP: + if ((instance_data->Get_State() & 4) == 0) { + return MSG_IGNORED; + } + +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + check_box->Win_Get_Owner(), GBM_SELECTED_RIGHT, reinterpret_cast(check_box), data_1); +#endif + instance_data->m_state &= ~4; + return MSG_HANDLED; + case GWM_MOUSE_ENTERING: + if ((instance_data->Get_Style() & GWS_MOUSE_TRACK) != 0) { + instance_data->m_state |= 2; +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + check_box->Win_Get_Owner(), GBM_MOUSE_ENTERING, reinterpret_cast(check_box), data_1); +#endif + } + + return MSG_HANDLED; + case GWM_MOUSE_LEAVING: + if ((instance_data->Get_Style() & GWS_MOUSE_TRACK) != 0) { + instance_data->m_state &= ~2; +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + check_box->Win_Get_Owner(), GBM_MOUSE_LEAVING, reinterpret_cast(check_box), data_1); +#endif + } + + return MSG_HANDLED; + case GWM_CHAR: + switch (data_1) { + case Keyboard::KEY_TAB: + case Keyboard::KEY_RIGHT: + case Keyboard::KEY_DOWN: + if ((data_2 & 2) != 0) { + g_theWindowManager->Win_Next_Tab(check_box); + } + + return MSG_HANDLED; + case Keyboard::KEY_RETURN: + case Keyboard::KEY_SPACE: + if ((data_2 & 2) != 0) { + instance_data->m_state ^= 4; +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + check_box->Win_Get_Owner(), GBM_SELECTED, reinterpret_cast(check_box), 0); +#endif + } + + return MSG_HANDLED; + case Keyboard::KEY_UP: + case Keyboard::KEY_LEFT: + if ((data_2 & 2) != 0) { + g_theWindowManager->Win_Prev_Tab(check_box); + } + + return MSG_HANDLED; + default: + return MSG_IGNORED; + } + default: + return MSG_IGNORED; + } +} + +WindowMsgHandledType Gadget_Check_Box_System( + GameWindow *check_box, unsigned int message, unsigned int data_1, unsigned int data_2) +{ + WinInstanceData *instance_data = check_box->Win_Get_Instance_Data(); + + if (message > GWM_INPUT_FOCUS) { + if (message != GGM_SET_LABEL) { + return MSG_IGNORED; + } + + check_box->Win_Set_Text(*reinterpret_cast(data_1)); + } else if (message == GWM_INPUT_FOCUS) { + if (data_1 != 0) { + instance_data->m_state = instance_data->m_state | 2; + } else { + instance_data->m_state = instance_data->m_state & ~2; + } + + g_theWindowManager->Win_Send_System_Msg( + instance_data->Get_Owner(), GGM_FOCUS_CHANGE, data_1, check_box->Win_Get_Window_Id()); + + if (data_1) { + *reinterpret_cast(data_2) = true; + } else { + *reinterpret_cast(data_2) = false; + } + } else if (message != GWM_CREATE && message != GWM_DESTROY) { + return MSG_IGNORED; + } + + return MSG_HANDLED; +} void Gadget_Check_Box_Set_Text(GameWindow *check_box, Utf16String text) { @@ -23,24 +156,41 @@ void Gadget_Check_Box_Set_Text(GameWindow *check_box, Utf16String text) #endif } -WindowMsgHandledType Gadget_Check_Box_Input( - GameWindow *check_box, unsigned int message, unsigned int data_1, unsigned int data_2) +void Gadget_Check_Box_Set_Checked(GameWindow *check_box, bool is_checked) { -#ifdef GAME_DLL - return Call_Function( - PICK_ADDRESS(0x005C2F10, 0x00A59950), check_box, message, data_1, data_2); -#else - return MSG_IGNORED; + WinInstanceData *instance_data = check_box->Win_Get_Instance_Data(); + + if (is_checked) { + instance_data->m_state = instance_data->m_state | 4; + } else { + instance_data->m_state = instance_data->m_state & ~4; + } + +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + check_box->Win_Get_Owner(), GBM_SELECTED, reinterpret_cast(check_box), 0); #endif } -WindowMsgHandledType Gadget_Check_Box_System( - GameWindow *check_box, unsigned int message, unsigned int data_1, unsigned int data_2) +void Gadget_Check_Box_Toggle(GameWindow *check_box) { -#ifdef GAME_DLL - return Call_Function( - PICK_ADDRESS(0x005C3210, 0x00A59CE1), check_box, message, data_1, data_2); -#else - return MSG_IGNORED; + WinInstanceData *instance_data = check_box->Win_Get_Instance_Data(); + + if ((instance_data->m_state & 4) != 0) { + instance_data->m_state = instance_data->m_state | 4; + } else { + instance_data->m_state = instance_data->m_state & ~4; + } + +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + check_box->Win_Get_Owner(), GBM_SELECTED, reinterpret_cast(check_box), 0); #endif } + +bool Gadget_Check_Box_Is_Checked(GameWindow *check_box) +{ + return (check_box->Win_Get_Instance_Data()->m_state & 4) != 0; +} diff --git a/src/game/client/gui/gadget/gadgetcheckbox.h b/src/game/client/gui/gadget/gadgetcheckbox.h index 455dbb835..d3d38d6e9 100644 --- a/src/game/client/gui/gadget/gadgetcheckbox.h +++ b/src/game/client/gui/gadget/gadgetcheckbox.h @@ -159,5 +159,5 @@ WindowMsgHandledType Gadget_Check_Box_System( void Gadget_Check_Box_Set_Text(GameWindow *check_box, Utf16String text); void Gadget_Check_Box_Set_Checked(GameWindow *check_box, bool is_checked); -void Gadget_check_Box_Toggle(GameWindow *check_box); -bool Gadget_Check_Box_Is_checked(GameWindow *check_box); +void Gadget_Check_Box_Toggle(GameWindow *check_box); +bool Gadget_Check_Box_Is_Checked(GameWindow *check_box); diff --git a/src/game/client/gui/gadget/gadgetcombobox.cpp b/src/game/client/gui/gadget/gadgetcombobox.cpp index c9631c143..b81f98ffd 100644 --- a/src/game/client/gui/gadget/gadgetcombobox.cpp +++ b/src/game/client/gui/gadget/gadgetcombobox.cpp @@ -19,90 +19,21 @@ #include "gadgettextentry.h" #include "gamewindow.h" -void Gadget_Combo_Box_Set_Enabled_Text_Colors(GameWindow *combo_box, int color, int border_color) -{ - if (combo_box != nullptr) { - _ComboBoxData *data = static_cast<_ComboBoxData *>(combo_box->Win_Get_User_Data()); - - if (data->m_listBox != nullptr) { - data->m_listBox->Win_Set_Enabled_Text_Colors(color, border_color); - } - - if (data->m_editBox != nullptr) { - data->m_editBox->Win_Set_Enabled_Text_Colors(color, border_color); - } - } -} - -void Gadget_Combo_Box_Set_Disabled_Text_Colors(GameWindow *combo_box, int color, int border_color) -{ - if (combo_box != nullptr) { - _ComboBoxData *data = static_cast<_ComboBoxData *>(combo_box->Win_Get_User_Data()); - - if (data->m_listBox != nullptr) { - data->m_listBox->Win_Set_Disabled_Text_Colors(color, border_color); - } - - if (data->m_editBox != nullptr) { - data->m_editBox->Win_Set_Disabled_Text_Colors(color, border_color); - } - } -} - -void Gadget_Combo_Box_Set_Hilite_Text_Colors(GameWindow *combo_box, int color, int border_color) -{ - if (combo_box != nullptr) { - _ComboBoxData *data = static_cast<_ComboBoxData *>(combo_box->Win_Get_User_Data()); - - if (data->m_listBox != nullptr) { - data->m_listBox->Win_Set_Hilite_Text_Colors(color, border_color); - } - - if (data->m_editBox != nullptr) { - data->m_editBox->Win_Set_Hilite_Text_Colors(color, border_color); - } - } -} - -void Gadget_Combo_Box_Set_IME_Composite_Text_Colors(GameWindow *combo_box, int color, int border_color) -{ - if (combo_box != nullptr) { - _ComboBoxData *data = static_cast<_ComboBoxData *>(combo_box->Win_Get_User_Data()); - - if (data->m_listBox != nullptr) { - data->m_listBox->Win_Set_IME_Composite_Text_Colors(color, border_color); - } - - if (data->m_editBox != nullptr) { - data->m_editBox->Win_Set_IME_Composite_Text_Colors(color, border_color); - } - } -} - -void Gadget_Combo_Box_Set_Font(GameWindow *combo_box, GameFont *font) +void Hide_List_Box(GameWindow *combo_box) { GameWindow *list_box = Gadget_Combo_Box_Get_List_Box(combo_box); if (list_box != nullptr) { - list_box->Win_Set_Font(font); - } - - GameWindow *edit_box = Gadget_Combo_Box_Get_Edit_Box(combo_box); - - if (edit_box != nullptr) { - edit_box->Win_Set_Font(font); - } - - DisplayString *string = combo_box->Win_Get_Instance_Data()->Get_Text_DisplayString(); - - if (string != nullptr) { - string->Set_Font(font); - } - - DisplayString *tooltip_string = combo_box->Win_Get_Instance_Data()->Get_Tooltip_DisplayString(); - - if (tooltip_string != nullptr) { - tooltip_string->Set_Font(font); + if (!list_box->Win_Is_Hidden()) { + list_box->Win_Hide(true); + int combo_width; + int combo_height; + int edit_width; + int edit_height; + Gadget_Combo_Box_Get_Edit_Box(combo_box)->Win_Get_Size(&edit_width, &edit_height); + combo_box->Win_Get_Size(&combo_width, &combo_height); + combo_box->Win_Set_Size(combo_width, edit_height); + } } } @@ -222,6 +153,30 @@ void Gadget_Combo_Box_Set_Is_Editable(GameWindow *combo_box, bool is_editable) } } +void Gadget_Combo_Box_Set_Letters_And_Numbers_Only(GameWindow *combo_box, bool letters_and_numbers_only) +{ + if (combo_box != nullptr) { + _ComboBoxData *data = static_cast<_ComboBoxData *>(combo_box->Win_Get_User_Data()); + data->m_lettersAndNumbersOnly = letters_and_numbers_only; + + if (data->m_entryData != nullptr) { + data->m_entryData->m_alphaNumericalOnly = letters_and_numbers_only; + } + } +} + +void Gadget_Combo_Box_Set_Ascii_Only(GameWindow *combo_box, bool ascii_only) +{ + if (combo_box != nullptr) { + _ComboBoxData *data = static_cast<_ComboBoxData *>(combo_box->Win_Get_User_Data()); + data->m_asciiOnly = ascii_only; + + if (data->m_entryData != nullptr) { + data->m_entryData->m_asciiOnly = ascii_only; + } + } +} + void Gadget_Combo_Box_Set_Max_Chars(GameWindow *combo_box, int max_chars) { if (combo_box != nullptr) { @@ -236,3 +191,193 @@ void Gadget_Combo_Box_Set_Max_Display(GameWindow *combo_box, int max_display) _ComboBoxData *data = static_cast<_ComboBoxData *>(combo_box->Win_Get_User_Data()); data->m_maxDisplay = max_display; } + +Utf16String Gadget_Combo_Box_Get_Text(GameWindow *combo_box) +{ + if (combo_box != nullptr) { + if ((combo_box->Win_Get_Style() & GWS_COMBO_BOX) != 0) { + return Gadget_Text_Entry_Get_Text(Gadget_Combo_Box_Get_Edit_Box(combo_box)); + } else { + return Utf16String::s_emptyString; + } + } else { + return Utf16String::s_emptyString; + } +} + +void Gadget_Combo_Box_Set_Text(GameWindow *combo_box, Utf16String text) +{ + if (combo_box != nullptr) { + Gadget_Text_Entry_Set_Text(Gadget_Combo_Box_Get_Edit_Box(combo_box), text); + } +} + +int Gadget_Combo_Box_Add_Entry(GameWindow *combo_box, Utf16String text, int color) +{ + if (combo_box != nullptr) { +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + return g_theWindowManager->Win_Send_System_Msg( + combo_box, GCM_ADD_ENTRY, reinterpret_cast(&text), color); +#else + return -1; +#endif + } else { + return -1; + } +} + +void Gadget_Combo_Box_Reset(GameWindow *combo_box) +{ + if (combo_box != nullptr) { + g_theWindowManager->Win_Send_System_Msg(combo_box, GCM_DEL_ALL, 0, 0); + } +} + +void Gadget_Combo_Box_Set_Font(GameWindow *combo_box, GameFont *font) +{ + GameWindow *list_box = Gadget_Combo_Box_Get_List_Box(combo_box); + + if (list_box != nullptr) { + list_box->Win_Set_Font(font); + } + + GameWindow *edit_box = Gadget_Combo_Box_Get_Edit_Box(combo_box); + + if (edit_box != nullptr) { + edit_box->Win_Set_Font(font); + } + + DisplayString *string = combo_box->Win_Get_Instance_Data()->Get_Text_DisplayString(); + + if (string != nullptr) { + string->Set_Font(font); + } + + DisplayString *tooltip_string = combo_box->Win_Get_Instance_Data()->Get_Tooltip_DisplayString(); + + if (tooltip_string != nullptr) { + tooltip_string->Set_Font(font); + } +} + +void Gadget_Combo_Box_Hide_List(GameWindow *combo_box) +{ + if (combo_box != nullptr) { + g_theWindowManager->Win_Send_System_Msg(combo_box, GGM_CLOSE, 0, 0); + } +} + +void Gadget_Combo_Box_Set_Enabled_Text_Colors(GameWindow *combo_box, int color, int border_color) +{ + if (combo_box != nullptr) { + _ComboBoxData *data = static_cast<_ComboBoxData *>(combo_box->Win_Get_User_Data()); + + if (data->m_listBox != nullptr) { + data->m_listBox->Win_Set_Enabled_Text_Colors(color, border_color); + } + + if (data->m_editBox != nullptr) { + data->m_editBox->Win_Set_Enabled_Text_Colors(color, border_color); + } + } +} + +void Gadget_Combo_Box_Set_Disabled_Text_Colors(GameWindow *combo_box, int color, int border_color) +{ + if (combo_box != nullptr) { + _ComboBoxData *data = static_cast<_ComboBoxData *>(combo_box->Win_Get_User_Data()); + + if (data->m_listBox != nullptr) { + data->m_listBox->Win_Set_Disabled_Text_Colors(color, border_color); + } + + if (data->m_editBox != nullptr) { + data->m_editBox->Win_Set_Disabled_Text_Colors(color, border_color); + } + } +} + +void Gadget_Combo_Box_Set_Hilite_Text_Colors(GameWindow *combo_box, int color, int border_color) +{ + if (combo_box != nullptr) { + _ComboBoxData *data = static_cast<_ComboBoxData *>(combo_box->Win_Get_User_Data()); + + if (data->m_listBox != nullptr) { + data->m_listBox->Win_Set_Hilite_Text_Colors(color, border_color); + } + + if (data->m_editBox != nullptr) { + data->m_editBox->Win_Set_Hilite_Text_Colors(color, border_color); + } + } +} + +void Gadget_Combo_Box_Set_IME_Composite_Text_Colors(GameWindow *combo_box, int color, int border_color) +{ + if (combo_box != nullptr) { + _ComboBoxData *data = static_cast<_ComboBoxData *>(combo_box->Win_Get_User_Data()); + + if (data->m_listBox != nullptr) { + data->m_listBox->Win_Set_IME_Composite_Text_Colors(color, border_color); + } + + if (data->m_editBox != nullptr) { + data->m_editBox->Win_Set_IME_Composite_Text_Colors(color, border_color); + } + } +} + +void Gadget_Combo_Box_Get_Selected_Pos(GameWindow *combo_box, int *selected_index) +{ + if (combo_box != nullptr) { +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + combo_box, GCM_GET_SELECTION, 0, reinterpret_cast(selected_index)); +#endif + } +} + +void Gadget_Combo_Box_Set_Selected_Pos(GameWindow *combo_box, int selected_index, bool dont_hide) +{ + if (combo_box != nullptr) { + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg(combo_box, GCM_SET_SELECTION, selected_index, dont_hide); + } +} + +void Gadget_Combo_Box_Set_Item_Data(GameWindow *combo_box, int index, void *data) +{ + if (combo_box != nullptr) { +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg(combo_box, GCM_SET_ITEM_DATA, index, reinterpret_cast(data)); +#endif + } +} + +void *Gadget_Combo_Box_Get_Item_Data(GameWindow *combo_box, int index) +{ + void *data = nullptr; + + if (combo_box != nullptr) { +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg(combo_box, GCM_GET_ITEM_DATA, index, reinterpret_cast(&data)); +#endif + } + + return data; +} + +int Gadget_Combo_Box_Get_Length(GameWindow *combo_box) +{ + _ComboBoxData *data = static_cast<_ComboBoxData *>(combo_box->Win_Get_User_Data()); + + if (data != nullptr) { + return data->m_entryCount; + } else { + return 0; + } +} diff --git a/src/game/client/gui/gadget/gadgetcombobox.h b/src/game/client/gui/gadget/gadgetcombobox.h index 57e0c0fa6..d36a6e15a 100644 --- a/src/game/client/gui/gadget/gadgetcombobox.h +++ b/src/game/client/gui/gadget/gadgetcombobox.h @@ -245,7 +245,7 @@ void Gadget_Combo_Box_Set_Max_Chars(GameWindow *combo_box, int max_chars); void Gadget_Combo_Box_Set_Max_Display(GameWindow *combo_box, int max_display); Utf16String Gadget_Combo_Box_Get_Text(GameWindow *combo_box); void Gadget_Combo_Box_Set_Text(GameWindow *combo_box, Utf16String text); -void Gadget_Combo_Box_Add_Entry(GameWindow *combo_box, Utf16String text, int color); +int Gadget_Combo_Box_Add_Entry(GameWindow *combo_box, Utf16String text, int color); void Gadget_Combo_Box_Reset(GameWindow *combo_box); void Gadget_Combo_Box_Hide_List(GameWindow *combo_box); void Gadget_Combo_Box_Get_Selected_Pos(GameWindow *combo_box, int *selected_index); diff --git a/src/game/client/gui/gadget/gadgetlistbox.cpp b/src/game/client/gui/gadget/gadgetlistbox.cpp index 86f72e167..1778e0c40 100644 --- a/src/game/client/gui/gadget/gadgetlistbox.cpp +++ b/src/game/client/gui/gadget/gadgetlistbox.cpp @@ -13,42 +13,147 @@ * LICENSE */ #include "gadgetlistbox.h" +#include "audioeventrts.h" +#include "audiomanager.h" #include "displaystring.h" +#include "displaystringmanager.h" #include "gadgetpushbutton.h" #include "gadgetslider.h" #include "gamewindow.h" #include "gamewindowmanager.h" -void Gadget_List_Box_Set_Font(GameWindow *list_box, GameFont *font) +void Gadget_List_Box_Get_Entry_Based_On_Coord(GameWindow *list_box, int x, int y, int &row, int &column) { + WinInstanceData *instance_data = list_box->Win_Get_Instance_Data(); _ListboxData *data = static_cast<_ListboxData *>(list_box->Win_Get_User_Data()); - DisplayString *string = list_box->Win_Get_Instance_Data()->Get_Text_DisplayString(); - if (string != nullptr) { - string->Set_Font(font); + int screen_x; + int screen_y; + list_box->Win_Get_Screen_Position(&screen_x, &screen_y); + + if (instance_data->Get_Text_Length() != 0) { + screen_y += g_theWindowManager->Win_Font_Height(instance_data->Get_Font()); } - DisplayString *tooltip_string = list_box->Win_Get_Instance_Data()->Get_Tooltip_DisplayString(); + int i1 = -2; + int i; - if (tooltip_string != nullptr) { - tooltip_string->Set_Font(font); + for (i = 0;; i++) { + if (i > 0 && data->m_listData[i - 1].m_listHeight > data->m_displayHeight + data->m_displayPos) { + break; + } + + if (i == data->m_endPos) { + i1 = -1; + break; + } + + if (data->m_listData[i].m_listHeight > data->m_displayPos + y - screen_y) { + break; + } } - if (data != nullptr) { - for (int i = 0; i < data->m_listLength; i++) { - if (data->m_listData[i].m_cell != nullptr) { - for (int j = 0; j < data->m_columns; j++) { - if (data->m_listData[i].m_cell[j].m_cellType == LISTBOX_TEXT) { - if (data->m_listData[i].m_cell[j].m_data != nullptr) { - static_cast(data->m_listData[i].m_cell[j].m_data)->Set_Font(font); - } - } + column = -1; + + if (i1 == -2) { + i1 = i; + int i2 = 0; + + for (i = 0; i < data->m_columns; i++) { + i2 += data->m_columnWidth[i]; + + if (x - screen_x < i2) { + column = i; + break; + } + } + } + + row = i1; +} + +void Gadget_List_Box_Get_Entry_Based_On_XY(GameWindow *list_box, int x, int y, int &row, int &column) +{ + Gadget_List_Box_Get_Entry_Based_On_Coord(list_box, x, y, row, column); +} + +void Do_Audio_Feedback(GameWindow *list_box) +{ + if (list_box) { + _ListboxData *data = static_cast<_ListboxData *>(list_box->Win_Get_User_Data()); + + if (data != nullptr) { + if (data->m_audioFeedback) { + AudioEventRTS event("GUIComboBoxClick"); + + if (g_theAudio != nullptr) { + g_theAudio->Add_Audio_Event(&event); } } } } } +int Get_List_Box_Top_Entry(_ListboxData *list) +{ + for (int i = 0;; i++) { + if (list->m_listData[i].m_listHeight > list->m_displayPos) { + return i; + } + + if (i >= list->m_endPos) { + break; + } + } + + return 0; +} + +void Adjust_Display(GameWindow *list_box, int adjustment, bool update_slider) +{ + _ListboxData *data = static_cast<_ListboxData *>(list_box->Win_Get_User_Data()); + int index = adjustment + Get_List_Box_Top_Entry(data); + + if (index >= 0) { + if (index >= data->m_endPos) { + index = data->m_endPos - 1; + } + } else { + index = 0; + } + + if (update_slider) { + if (index <= 0) { + data->m_displayPos = 0; + } else { + data->m_displayPos = data->m_listData[index - 1].m_listHeight + 1; + } + } + + if (data->m_slider != nullptr) { + _SliderData *silder_data = static_cast<_SliderData *>(data->m_slider->Win_Get_User_Data()); + int slider_width; + int slider_height; + data->m_slider->Win_Get_Size(&slider_width, &slider_height); + silder_data->m_maxVal = data->m_totalHeight - (data->m_displayHeight - 2) + 1; + + if (silder_data->m_maxVal < 0) { + silder_data->m_maxVal = 0; + } + + GameWindow *child = data->m_slider->Win_Get_Child(); + int child_width; + int child_height; + child->Win_Get_Size(&child_width, &child_height); + silder_data->m_numTicks = (float)(slider_height - child_height) / (float)silder_data->m_maxVal; + + if (update_slider) { + g_theWindowManager->Win_Send_System_Msg( + data->m_slider, GSM_SET_SLIDER, silder_data->m_maxVal - data->m_displayPos, 0); + } + } +} + WindowMsgHandledType Gadget_List_Box_Input( GameWindow *list_box, unsigned int message, unsigned int data_1, unsigned int data_2) { @@ -71,6 +176,224 @@ WindowMsgHandledType Gadget_List_Box_Multi_Input( #endif } +void Remove_Selection(_ListboxData *data, int selection) +{ + memcpy(&data->m_selections[selection], &data->m_selections[selection + 1], 4 * (data->m_listLength - selection)); + data->m_selections[data->m_listLength - 1] = -1; +} + +void Compute_Total_Height(GameWindow *list_box) +{ + int total_height = 0; + _ListboxData *data = static_cast<_ListboxData *>(list_box->Win_Get_User_Data()); + WinInstanceData *instance_data = list_box->Win_Get_Instance_Data(); + + for (int i = 0; i < data->m_endPos; i++) { + if (data->m_listData[i].m_cell == nullptr) { + continue; + } + + int height = 0; + + for (int j = 0; j < data->m_columns; j++) { + int new_height = 0; + + if (data->m_listData[i].m_cell[j].m_cellType != LISTBOX_TEXT) { + if (data->m_listData[i].m_cell[j].m_cellType != LISTBOX_IMAGE) { + if (new_height > height) { + height = new_height; + } + + continue; + } + + if (data->m_listData[i].m_cell[j].m_height > 0) { + new_height = data->m_listData[i].m_cell[j].m_height + 1; + + if (new_height > height) { + height = new_height; + } + + continue; + } + + new_height = g_theWindowManager->Win_Font_Height(instance_data->Get_Font()); + + if (new_height > height) { + height = new_height; + } + + continue; + } + + if ((list_box->Win_Get_Status() & GWS_TAB_PANE) != 0) { + new_height = g_theWindowManager->Win_Font_Height(instance_data->Get_Font()); + + if (new_height > height) { + height = new_height; + } + + continue; + } + + DisplayString *string = static_cast(data->m_listData[i].m_cell[j].m_data); + + if (string != nullptr) { + string->Get_Size(nullptr, &new_height); + } + + if (new_height > height) { + height = new_height; + } + } + + data->m_listData[i].m_height = height; + total_height += data->m_listData[i].m_height + 1; + data->m_listData[i].m_listHeight = total_height; + } + + data->m_totalHeight = total_height; + Adjust_Display(list_box, 0, true); +} + +int Add_Image_Entry( + Image *image, int color, int row, int column, GameWindow *list_box, bool overwrite, int height, int width) +{ + _ListboxData *data = static_cast<_ListboxData *>(list_box->Win_Get_User_Data()); + + if (column < data->m_columns && row < data->m_listLength) { + if (row == -1) { + row = data->m_insertPos++; + data->m_endPos++; + } + + if (column == -1) { + column = 0; + } + + _ListEntryRow *list_row = &data->m_listData[row]; + + if (!list_row->m_cell) { + list_row->m_cell = new _ListEntryCell[data->m_columns]; + memset(list_row->m_cell, 0, sizeof(_ListEntryCell) * data->m_columns); + } + + if (list_row->m_cell[column].m_cellType == LISTBOX_TEXT) { + g_theDisplayStringManager->Free_Display_String(static_cast(list_row->m_cell[column].m_data)); + } + + list_row->m_cell[column].m_cellType = LISTBOX_IMAGE; + list_row->m_cell[column].m_data = image; + list_row->m_cell[column].m_textColor = color; + list_row->m_cell[column].m_height = width; + list_row->m_cell[column].m_width = height; + Compute_Total_Height(list_box); + return row; + } else { + captainslog_dbgassert(false, "Tried to add Image to Listbox at invalid position"); + return -1; + } +} + +int Move_Rows_Down(_ListboxData *data, int row) +{ + int size = sizeof(_ListEntryRow) * (data->m_endPos - row); + char *buf = new char[size]; + memcpy(buf, &data->m_listData[row], size); + memcpy(&data->m_listData[row + 1], buf, size); + delete[] buf; + data->m_insertPos = ++data->m_endPos; + data->m_listData[row].m_cell = 0; + data->m_listData[row].m_height = 0; + data->m_listData[row].m_listHeight = 0; + + if (data->m_multiSelect) { + for (int i = 0; data->m_selections[i] >= 0; i++) { + if (row <= data->m_selections[i]) { + data->m_selections[i]++; + } + } + } else if (data->m_selectPos >= row) { + data->m_selectPos++; + } + + return 1; +} + +int Add_Entry(Utf16String *string, int color, int row, int column, GameWindow *list_box, bool overwrite) +{ + _ListboxData *data = static_cast<_ListboxData *>(list_box->Win_Get_User_Data()); + + if (column < data->m_columns && row < data->m_listLength) { + if (row == -1) { + row = data->m_insertPos++; + data->m_endPos++; + } + + if (column == -1) { + column = 0; + } + + int wrap = data->m_columnWidth[column] - 7; + int adjust = 0; + _ListEntryRow *list_row = &data->m_listData[row]; + + if (list_row->m_cell) { + if (!overwrite) { + Move_Rows_Down(data, row); + list_row->m_cell = new _ListEntryCell[data->m_columns]; + memset(list_row->m_cell, 0, sizeof(_ListEntryCell) * data->m_columns); + adjust = 1; + } + } else { + list_row->m_cell = new _ListEntryCell[data->m_columns]; + memset(list_row->m_cell, 0, sizeof(_ListEntryCell) * data->m_columns); + adjust = 1; + } + + list_row->m_cell[column].m_cellType = LISTBOX_TEXT; + list_row->m_cell[column].m_textColor = color; + + if (!list_row->m_cell[column].m_data) { + list_row->m_cell[column].m_data = g_theDisplayStringManager->New_Display_String(); + } + + DisplayString *text = static_cast(list_row->m_cell[column].m_data); + + if ((list_box->Win_Get_Status() & GWS_TAB_PANE) == 0) { + text->Set_Word_Wrap(wrap); + } + + text->Set_Font(list_box->Win_Get_Font()); + + if (overwrite) { + int height = list_row->m_height; + int list_height = list_row->m_listHeight; + + if (list_height == 0 && row) { + list_height = data->m_listData[row - 1].m_listHeight; + } + + int size; + text->Get_Size(nullptr, &size); + + if (size > height) { + list_row->m_height = size; + list_row->m_listHeight = adjust + (size - height + list_height); + data->m_totalHeight += adjust + size - height; + Adjust_Display(list_box, 0, true); + } + } else { + Compute_Total_Height(list_box); + } + + return row; + } else { + captainslog_dbgassert(false, "Tried to add Text to Listbox at invalid position"); + return -1; + } +} + WindowMsgHandledType Gadget_List_Box_System( GameWindow *list_box, unsigned int message, unsigned int data_1, unsigned int data_2) { @@ -159,180 +482,421 @@ void Gadget_List_Box_Set_Colors(GameWindow *list_box, } } -void Gadget_List_Box_Create_Scroll_Bar(GameWindow *list_box) -{ -#ifdef GAME_DLL - Call_Function(PICK_ADDRESS(0x005E7EF0, 0x00A0846C), list_box); -#endif -} - -void Gadget_List_Box_Set_List_Length(GameWindow *list_box, int new_length) +Utf16String Gadget_List_Box_Get_Text(GameWindow *list_box, int row, int column) { -#ifdef GAME_DLL - Call_Function(PICK_ADDRESS(0x005E8110, 0x00A08933), list_box, new_length); -#endif + int color; + return Gadget_List_Box_Get_Text_And_Color(list_box, &color, row, column); } -void Gadget_List_Box_Set_Audio_Feedback(GameWindow *list_box, bool audio_feedback) +Utf16String Gadget_List_Box_Get_Text_And_Color(GameWindow *list_box, int *color, int row, int column) { - if (list_box != nullptr) { - _ListboxData *lb_data = static_cast<_ListboxData *>(list_box->Win_Get_User_Data()); + *color = 0; - if (lb_data != nullptr) { - lb_data->m_audioFeedback = audio_feedback; + if (list_box == nullptr || row == -1 || column == -1) { + return Utf16String::s_emptyString; + } else { + if ((list_box->Win_Get_Style() & GWS_SCROLL_LISTBOX) != 0) { + _TextAndColor text; + _GetTextStruct get; + get.column = column; + get.row = row; +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + list_box, GLM_GET_TEXT, reinterpret_cast(&get), reinterpret_cast(&text)); +#endif + *color = text.color; + return text.string; + } else { + return Utf16String::s_emptyString; } } } -int Get_List_Box_Top_Entry(_ListboxData *list) +int Gadget_List_Box_Add_Entry_Text(GameWindow *list_box, Utf16String text, int color, int row, int column, bool overwrite) { - for (int i = 0;; i++) { - if (list->m_listData[i].m_listHeight > list->m_displayPos) { - return i; + if (list_box != nullptr) { + if (text.Is_Empty()) { + text = U_CHAR(" "); } - if (i >= list->m_endPos) { - break; + _AddMessageStruct entry; + entry.row = row; + entry.column = column; + entry.type = 1; + entry.data = &text; + entry.overwrite = overwrite; + entry.width = -1; + entry.height = -1; + _ListboxData *data = static_cast<_ListboxData *>(list_box->Win_Get_User_Data()); + + bool list_exceeded = data->m_listLength <= data->m_endPos; + int i = list_exceeded ? 0 : 1; + int bottom = Gadget_List_Box_Get_Bottom_Visible_Entry(list_box); + int index = 0; +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + index = static_cast( + g_theWindowManager->Win_Send_System_Msg(list_box, GLM_ADD_ENTRY, reinterpret_cast(&entry), color)); +#endif + if (data->m_scrollIfAtEnd && (index - bottom) == i && Gadget_List_Box_Is_Full(list_box)) { + Gadget_List_Box_Set_Bottom_Visible_Entry(list_box, index); } - } - return 0; + return index; + } else { + return -1; + } } -void Adjust_Display(GameWindow *list_box, int adjustment, bool update_slider) -{ +int Gadget_List_Box_Add_Entry_Image( + GameWindow *list_box, const Image *image, int row, int column, int width, int height, bool overwrite, int color) +{ + _AddMessageStruct entry; + entry.row = row; + entry.column = column; + entry.type = 2; + entry.data = const_cast(image); + entry.overwrite = overwrite; + entry.width = width; + entry.height = height; + int index = 0; +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + index = static_cast( + g_theWindowManager->Win_Send_System_Msg(list_box, GLM_ADD_ENTRY, reinterpret_cast(&entry), color)); +#endif + return index; +} + +int Gadget_List_Box_Add_Entry_Image(GameWindow *list_box, const Image *image, int row, int column, bool overwrite, int color) +{ + return Gadget_List_Box_Add_Entry_Image(list_box, image, row, column, -1, -1, overwrite, color); +} + +void Gadget_List_Box_Set_Font(GameWindow *list_box, GameFont *font) +{ _ListboxData *data = static_cast<_ListboxData *>(list_box->Win_Get_User_Data()); - int index = adjustment + Get_List_Box_Top_Entry(data); + DisplayString *string = list_box->Win_Get_Instance_Data()->Get_Text_DisplayString(); - if (index >= 0) { - if (index >= data->m_endPos) { - index = data->m_endPos - 1; + if (string != nullptr) { + string->Set_Font(font); + } + + DisplayString *tooltip_string = list_box->Win_Get_Instance_Data()->Get_Tooltip_DisplayString(); + + if (tooltip_string != nullptr) { + tooltip_string->Set_Font(font); + } + + if (data != nullptr) { + for (int i = 0; i < data->m_listLength; i++) { + if (data->m_listData[i].m_cell != nullptr) { + for (int j = 0; j < data->m_columns; j++) { + if (data->m_listData[i].m_cell[j].m_cellType == LISTBOX_TEXT) { + if (data->m_listData[i].m_cell[j].m_data != nullptr) { + static_cast(data->m_listData[i].m_cell[j].m_data)->Set_Font(font); + } + } + } + } } + } +} + +void Gadget_List_Box_Create_Scroll_Bar(GameWindow *list_box) +{ + _ListboxData *data = static_cast<_ListboxData *>(list_box->Win_Get_User_Data()); + WinInstanceData instance_data; + _SliderData slider_data; + memset(&slider_data, 0, sizeof(slider_data)); + int status = list_box->Win_Get_Status(); + bool has_text = false; + + int width; + int height; + list_box->Win_Get_Size(&width, &height); + + if (list_box->Win_Get_Text_Length() != 0) { + has_text = true; + } + + status &= ~(WIN_STATUS_BORDER | WIN_STATUS_NO_INPUT | WIN_STATUS_HIDDEN); + int font_height = g_theWindowManager->Win_Font_Height(list_box->Win_Get_Font()); + int i1; + int i2; + + if (has_text) { + i1 = font_height + 1; } else { - index = 0; + i1 = 0; } - if (update_slider) { - if (index <= 0) { - data->m_displayPos = 0; - } else { - data->m_displayPos = data->m_listData[index - 1].m_listHeight + 1; - } + if (has_text) { + i2 = height - (font_height + 1); + } else { + i2 = height; } - if (data->m_slider != nullptr) { - _SliderData *silder_data = static_cast<_SliderData *>(data->m_slider->Win_Get_User_Data()); - int slider_width; - int slider_height; - data->m_slider->Win_Get_Size(&slider_width, &slider_height); - silder_data->m_maxVal = data->m_totalHeight - (data->m_displayHeight - 2) + 1; + instance_data.Init(); + int i3 = 21; + int i4 = 22; + status |= WIN_STATUS_IMAGE; + instance_data.m_owner = list_box; + instance_data.m_style = GWS_PUSH_BUTTON; - if (silder_data->m_maxVal < 0) { - silder_data->m_maxVal = 0; - } + if ((list_box->Win_Get_Style() & GWS_MOUSE_TRACK) != 0) { + instance_data.m_style |= GWS_MOUSE_TRACK; + } - GameWindow *child = data->m_slider->Win_Get_Child(); - int child_width; - int child_height; - child->Win_Get_Size(&child_width, &child_height); - silder_data->m_numTicks = (float)(slider_height - child_height) / (float)silder_data->m_maxVal; + data->m_upButton = g_theWindowManager->Go_Go_Gadget_Push_Button(list_box, + status | WIN_STATUS_ENABLED | WIN_STATUS_ACTIVE, + width - i3 - 2, + i1 + 2, + i3, + i4, + &instance_data, + nullptr, + true); + instance_data.Init(); + instance_data.m_style = GWS_PUSH_BUTTON; + instance_data.m_owner = list_box; - if (update_slider) { - g_theWindowManager->Win_Send_System_Msg( - data->m_slider, GSM_SET_SLIDER, silder_data->m_maxVal - data->m_displayPos, 0); - } + if ((list_box->Win_Get_Style() & GWS_MOUSE_TRACK) != 0) { + instance_data.m_style |= GWS_MOUSE_TRACK; } -} -void Gadget_List_Box_Set_Top_Visible_Entry(GameWindow *list_box, int row) -{ - if (list_box != nullptr) { - if (list_box->Win_Get_User_Data() != nullptr) { - Adjust_Display(list_box, row - Gadget_List_Box_Get_Top_Visible_Entry(list_box), true); - } + data->m_downButton = g_theWindowManager->Go_Go_Gadget_Push_Button(list_box, + status | WIN_STATUS_ENABLED | WIN_STATUS_ACTIVE, + width - i3 - 2, + i2 + i1 - i4 - 2, + i3, + i4, + &instance_data, + nullptr, + true); + + instance_data.Init(); + instance_data.m_style = GWS_VERT_SLIDER; + instance_data.m_owner = list_box; + + if ((list_box->Win_Get_Style() & GWS_MOUSE_TRACK) != 0) { + instance_data.m_style |= GWS_MOUSE_TRACK; } + + memset(&slider_data, 0, sizeof(slider_data)); + data->m_slider = g_theWindowManager->Go_Go_Gadget_Slider(list_box, + status | WIN_STATUS_ENABLED | WIN_STATUS_ACTIVE, + width - i3 - 2, + i1 + i4 + 3, + i3, + i2 - 2 * i4 - 6, + &instance_data, + &slider_data, + nullptr, + true); + data->m_scrollBar = true; } -void Gadget_List_Box_Set_Selected(GameWindow *list_box, int select_count, int *select_list) +void Gadget_List_Box_Add_Multi_Select(GameWindow *list_box) { -#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a - // pointer to an unsigned int on 64 bit - if (list_box != nullptr) { - g_theWindowManager->Win_Send_System_Msg( - list_box, GLM_SET_SELECTION, select_count, reinterpret_cast(select_list)); + _ListboxData *data = static_cast<_ListboxData *>(list_box->Win_Get_User_Data()); + captainslog_dbgassert(data != nullptr && data->m_selections == nullptr, "selections is not NULL"); + data->m_selections = new int[data->m_listLength]; + captainslog_debug("Enable list box multi select: listLength (select) = %d * %d = %d bytes;", + data->m_listLength, + 4, + 4 * data->m_listLength); + + if (data->m_selections != nullptr) { + memset(data->m_selections, -1, 4 * data->m_listLength); + data->m_multiSelect = 1; + list_box->Win_Set_Input_Func(Gadget_List_Box_Multi_Input); + } else { + delete data->m_listData; } -#endif } -void Gadget_List_Box_Set_Item_Data(GameWindow *list_box, void *data, int row, int column) +void Gadget_List_Box_Remove_Multi_Select(GameWindow *list_box) { -#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a - // pointer to an unsigned int on 64 bit - ICoord2D pos; - pos.x = column; - pos.y = row; + _ListboxData *data = static_cast<_ListboxData *>(list_box->Win_Get_User_Data()); - if (list_box != nullptr) { - g_theWindowManager->Win_Send_System_Msg( - list_box, GLM_SET_ITEM_DATA, reinterpret_cast(&pos), reinterpret_cast(data)); + if (data->m_selections != nullptr) { + delete data->m_selections; + data->m_selections = nullptr; } -#endif + + data->m_multiSelect = false; + list_box->Win_Set_Input_Func(Gadget_List_Box_Input); } -void Gadget_List_Box_Reset(GameWindow *list_box) +void Gadget_List_Box_Set_List_Length(GameWindow *list_box, int new_length) { - if (list_box != nullptr) { - g_theWindowManager->Win_Send_System_Msg(list_box, GLM_DEL_ALL, 0, 0); + _ListboxData *data = static_cast<_ListboxData *>(list_box->Win_Get_User_Data()); + captainslog_dbgassert(data != nullptr, "We don't have our needed listboxData!"); + + if (data != nullptr) { + captainslog_dbgassert(data->m_columns > 0, "We need at least one Column in the listbox"); + + if (data->m_columns >= 1) { + int columns = data->m_columns; + _ListEntryRow *row = new _ListEntryRow[new_length]; + captainslog_dbgassert(row != nullptr, "Unable to allocate new data structures for the Listbox"); + + if (row != nullptr) { + memset(row, 0, 12 * new_length); + + if (new_length < data->m_listLength) { + if (data->m_displayPos > new_length) { + data->m_displayPos = new_length; + } + + if (data->m_selectPos > new_length || data->m_multiSelect) { + data->m_selectPos = -1; + } + + if (data->m_insertPos > new_length) { + data->m_insertPos = new_length; + } + + data->m_endPos = new_length; + memcpy(row, data->m_listData, 12 * new_length); + } else { + memcpy(row, data->m_listData, 12 * data->m_listLength); + } + + for (int i = 0; i < data->m_listLength; i++) { + _ListEntryCell *cell = data->m_listData[i].m_cell; + for (int j = columns - 1; j >= 0 && cell; --j) { + if (i >= new_length && cell[j].m_cellType == LISTBOX_TEXT && i >= new_length) { + if (cell[j].m_data != nullptr) { + g_theDisplayStringManager->Free_Display_String(static_cast(cell[j].m_data)); + } + } + } + + if (i >= new_length) { + delete[] data->m_listData[i].m_cell; + } + + data->m_listData[i].m_cell = nullptr; + } + + data->m_listLength = new_length; + + if (data->m_listData != nullptr) { + delete[] data->m_listData; + } + + data->m_listData = row; + + Compute_Total_Height(list_box); + + if (data->m_listData != nullptr) { + if (data->m_multiSelect) { + Gadget_List_Box_Remove_Multi_Select(list_box); + Gadget_List_Box_Add_Multi_Select(list_box); + } + } else { + captainslog_debug("Unable to allocate listbox data pointer"); + } + } + } } } -int Gadget_List_Box_Get_Top_Visible_Entry(GameWindow *list_box) +int Gadget_List_Box_Get_List_Length(GameWindow *list_box) { - if (list_box == nullptr) { - return false; - } - _ListboxData *data = static_cast<_ListboxData *>(list_box->Win_Get_User_Data()); - if (data != nullptr) { - return Get_List_Box_Top_Entry(data); + if (data->m_multiSelect) { + return data->m_listLength; } else { - return 0; + return 1; } } -int Gadget_List_Box_Get_Num_Columns(GameWindow *list_box) +int Gadget_List_Box_Get_Num_Entries(GameWindow *list_box) { if (list_box == nullptr) { - return false; + return 0; } _ListboxData *data = static_cast<_ListboxData *>(list_box->Win_Get_User_Data()); if (data != nullptr) { - return data->m_columns; + return data->m_endPos; } else { return 0; } } -int Gadget_List_Box_Get_Column_Width(GameWindow *list_box, int column) +void Gadget_List_Box_Get_Selected(GameWindow *list_box, int *select_list) { - if (list_box == nullptr) { - return false; +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + if (list_box != nullptr) { + g_theWindowManager->Win_Send_System_Msg(list_box, GLM_GET_SELECTION, 0, reinterpret_cast(select_list)); } +#endif +} - _ListboxData *data = static_cast<_ListboxData *>(list_box->Win_Get_User_Data()); +void Gadget_List_Box_Set_Selected(GameWindow *list_box, int select_index) +{ +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + if (list_box != nullptr) { + g_theWindowManager->Win_Send_System_Msg( + list_box, GLM_SET_SELECTION, reinterpret_cast(&select_index), 1); + } +#endif +} - if (data == nullptr) { - return 0; +void Gadget_List_Box_Set_Selected(GameWindow *list_box, int select_count, int *select_list) +{ +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + if (list_box != nullptr) { + g_theWindowManager->Win_Send_System_Msg( + list_box, GLM_SET_SELECTION, select_count, reinterpret_cast(select_list)); } +#endif +} - if (data->m_columns > column && column >= 0) { - return data->m_columnWidth[column]; +void Gadget_List_Box_Reset(GameWindow *list_box) +{ + if (list_box != nullptr) { + g_theWindowManager->Win_Send_System_Msg(list_box, GLM_DEL_ALL, 0, 0); } +} - return 0; +void Gadget_List_Box_Set_Item_Data(GameWindow *list_box, void *data, int row, int column) +{ +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + ICoord2D pos; + pos.x = column; + pos.y = row; + + if (list_box != nullptr) { + g_theWindowManager->Win_Send_System_Msg( + list_box, GLM_SET_ITEM_DATA, reinterpret_cast(&pos), reinterpret_cast(data)); + } +#endif +} + +void *Gadget_List_Box_Get_Item_Data(GameWindow *list_box, int row, int column) +{ + void *data = nullptr; + _GetTextStruct get; + get.column = column; + get.row = row; +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + list_box, GLM_GET_ITEM_DATA, reinterpret_cast(&get), reinterpret_cast(&data)); +#endif + return data; } int Get_List_Box_Bottom_Entry(_ListboxData *list) @@ -373,89 +937,91 @@ int Gadget_List_Box_Get_Bottom_Visible_Entry(GameWindow *list_box) } } -int Gadget_List_Box_Add_Entry_Text(GameWindow *list_box, Utf16String text, int color, int row, int column, bool overwrite) +bool Gadget_List_Box_Is_Full(GameWindow *list_box) +{ + if (list_box == nullptr) { + return false; + } + + _ListboxData *data = static_cast<_ListboxData *>(list_box->Win_Get_User_Data()); + return data != nullptr + && data->m_listData[Get_List_Box_Bottom_Entry(data)].m_listHeight >= data->m_displayPos + data->m_displayHeight - 5; +} + +void Gadget_List_Box_Set_Bottom_Visible_Entry(GameWindow *list_box, int row) { if (list_box != nullptr) { - if (text.Is_Empty()) { - text = U_CHAR(" "); + if (list_box->Win_Get_User_Data() != nullptr) { + Adjust_Display(list_box, row - Gadget_List_Box_Get_Bottom_Visible_Entry(list_box) + 1, true); } + } +} - _AddMessageStruct entry; - entry.row = row; - entry.column = column; - entry.type = 1; - entry.data = &text; - entry.overwrite = overwrite; - entry.width = -1; - entry.height = -1; - _ListboxData *data = static_cast<_ListboxData *>(list_box->Win_Get_User_Data()); +int Gadget_List_Box_Get_Top_Visible_Entry(GameWindow *list_box) +{ + if (list_box == nullptr) { + return false; + } - bool list_exceeded = data->m_listLength <= data->m_endPos; - int i = list_exceeded ? 0 : 1; - int bottom = Gadget_List_Box_Get_Bottom_Visible_Entry(list_box); - int index = 0; -#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a - // pointer to an unsigned int on 64 bit - index = static_cast( - g_theWindowManager->Win_Send_System_Msg(list_box, GLM_ADD_ENTRY, reinterpret_cast(&entry), color)); -#endif - if (data->m_scrollIfAtEnd && (index - bottom) == i && Gadget_List_Box_Is_Full(list_box)) { - Gadget_List_Box_Set_Bottom_Visible_Entry(list_box, index); - } + _ListboxData *data = static_cast<_ListboxData *>(list_box->Win_Get_User_Data()); - return index; + if (data != nullptr) { + return Get_List_Box_Top_Entry(data); } else { - return -1; + return 0; } } -int Gadget_List_Box_Add_Entry_Image( - GameWindow *list_box, const Image *image, int row, int column, int width, int height, bool overwrite, int color) +void Gadget_List_Box_Set_Top_Visible_Entry(GameWindow *list_box, int row) { - _AddMessageStruct entry; - entry.row = row; - entry.column = column; - entry.type = 2; - entry.data = const_cast(image); - entry.overwrite = overwrite; - entry.width = width; - entry.height = height; - int index = 0; -#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a - // pointer to an unsigned int on 64 bit - index = static_cast( - g_theWindowManager->Win_Send_System_Msg(list_box, GLM_ADD_ENTRY, reinterpret_cast(&entry), color)); -#endif - return index; + if (list_box != nullptr) { + if (list_box->Win_Get_User_Data() != nullptr) { + Adjust_Display(list_box, row - Gadget_List_Box_Get_Top_Visible_Entry(list_box), true); + } + } } -void Gadget_List_Box_Set_Selected(GameWindow *list_box, int select_index) +void Gadget_List_Box_Set_Audio_Feedback(GameWindow *list_box, bool audio_feedback) { -#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a - // pointer to an unsigned int on 64 bit if (list_box != nullptr) { - g_theWindowManager->Win_Send_System_Msg( - list_box, GLM_SET_SELECTION, reinterpret_cast(&select_index), 1); + _ListboxData *lb_data = static_cast<_ListboxData *>(list_box->Win_Get_User_Data()); + + if (lb_data != nullptr) { + lb_data->m_audioFeedback = audio_feedback; + } } -#endif } -void Gadget_List_Box_Set_Bottom_Visible_Entry(GameWindow *list_box, int row) +int Gadget_List_Box_Get_Num_Columns(GameWindow *list_box) { - if (list_box != nullptr) { - if (list_box->Win_Get_User_Data() != nullptr) { - Adjust_Display(list_box, row - Gadget_List_Box_Get_Bottom_Visible_Entry(list_box) + 1, true); - } + if (list_box == nullptr) { + return false; + } + + _ListboxData *data = static_cast<_ListboxData *>(list_box->Win_Get_User_Data()); + + if (data != nullptr) { + return data->m_columns; + } else { + return 0; } } -bool Gadget_List_Box_Is_Full(GameWindow *list_box) +int Gadget_List_Box_Get_Column_Width(GameWindow *list_box, int column) { if (list_box == nullptr) { return false; } _ListboxData *data = static_cast<_ListboxData *>(list_box->Win_Get_User_Data()); - return data != nullptr - && data->m_listData[Get_List_Box_Bottom_Entry(data)].m_listHeight >= data->m_displayPos + data->m_displayHeight - 5; + + if (data == nullptr) { + return 0; + } + + if (data->m_columns > column && column >= 0) { + return data->m_columnWidth[column]; + } + + return 0; } diff --git a/src/game/client/gui/gadget/gadgetpushbutton.cpp b/src/game/client/gui/gadget/gadgetpushbutton.cpp index addcd9a12..ca925e364 100644 --- a/src/game/client/gui/gadget/gadgetpushbutton.cpp +++ b/src/game/client/gui/gadget/gadgetpushbutton.cpp @@ -13,92 +13,446 @@ * LICENSE */ #include "gadgetpushbutton.h" +#include "audioeventrts.h" +#include "audiomanager.h" #include "gamewindowmanager.h" +#include "keyboard.h" -void Gadget_Button_Set_Text(GameWindow *push_button, Utf16String text) +bool Button_Triggers_On_Mouse_Down(GameWindow *push_button) { -#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a - // pointer to an unsigned int on 64 bit - g_theWindowManager->Win_Send_System_Msg(push_button, GGM_SET_LABEL, reinterpret_cast(&text), 0); -#endif + if ((push_button->Win_Get_Status() & WIN_STATUS_CHECK_LIKE) != 0) { + return true; + } + + return (push_button->Win_Get_Status() & WIN_STATUS_ON_MOUSE_DOWN) != 0; } WindowMsgHandledType Gadget_Push_Button_Input( GameWindow *push_button, unsigned int message, unsigned int data_1, unsigned int data_2) { -#ifdef GAME_DLL - return Call_Function( - PICK_ADDRESS(0x005ABB40, 0x008F44B0), push_button, message, data_1, data_2); -#else - return MSG_IGNORED; + WinInstanceData *instance_data = push_button->Win_Get_Instance_Data(); + + switch (message) { + case GWM_LEFT_DOWN: { + _PushButtonData *data = static_cast<_PushButtonData *>(push_button->Win_Get_User_Data()); + AudioEventRTS click; + + if (data != nullptr && data->m_altSound.Is_Not_Empty()) { + click.Set_Event_Name(data->m_altSound); + } else { + click.Set_Event_Name("GUIClick"); + } + + if (g_theAudio != nullptr) { + g_theAudio->Add_Audio_Event(&click); + } + + if ((push_button->Win_Get_Status() & WIN_STATUS_CHECK_LIKE) != 0) { + if ((instance_data->m_state & 4) != 0) { + instance_data->m_state &= ~4; + } else { + instance_data->m_state |= 4; + } + } else { + instance_data->m_state |= 4; + } + + if (Button_Triggers_On_Mouse_Down(push_button)) { +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + instance_data->Get_Owner(), GBM_SELECTED, reinterpret_cast(push_button), data_1); +#endif + } + + return MSG_HANDLED; + } + case GWM_LEFT_UP: { + if ((instance_data->Get_State() & 4) == 0 || (push_button->Win_Get_Status() & WIN_STATUS_CHECK_LIKE) != 0) { + return MSG_IGNORED; + } + + if (!Button_Triggers_On_Mouse_Down(push_button)) { +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + instance_data->Get_Owner(), GBM_SELECTED, reinterpret_cast(push_button), data_1); +#endif + } + + instance_data->m_state &= ~4; + return MSG_HANDLED; + } + case GWM_LEFT_DRAG: +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + instance_data->Get_Owner(), GGM_LEFT_DRAG, reinterpret_cast(push_button), data_1); +#endif + return MSG_HANDLED; + case GWM_RIGHT_DOWN: { + _PushButtonData *data = static_cast<_PushButtonData *>(push_button->Win_Get_User_Data()); + AudioEventRTS click; + + if (data != nullptr && data->m_altSound.Is_Not_Empty()) { + click.Set_Event_Name(data->m_altSound); + } else { + click.Set_Event_Name("GUIClick"); + } + + if ((instance_data->Get_Status() & WIN_STATUS_RIGHT_CLICK) == 0) { + return MSG_IGNORED; + } + + if (g_theAudio != nullptr) { + g_theAudio->Add_Audio_Event(&click); + } + + if ((push_button->Win_Get_Status() & WIN_STATUS_CHECK_LIKE) != 0) { + if ((instance_data->m_state & 4) != 0) { + instance_data->m_state &= ~4; + } else { + instance_data->m_state |= 4; + } + +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + instance_data->Get_Owner(), GBM_SELECTED_RIGHT, reinterpret_cast(push_button), data_1); #endif + } else { + instance_data->m_state |= 4; + } + + return MSG_HANDLED; + } + case GWM_RIGHT_UP: { + if ((instance_data->Get_Status() & WIN_STATUS_RIGHT_CLICK) == 0) { + return MSG_IGNORED; + } + + if ((instance_data->Get_State() & 4) == 0 || (push_button->Win_Get_Status() & WIN_STATUS_CHECK_LIKE) != 0) { + return MSG_IGNORED; + } + +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + instance_data->Get_Owner(), GBM_SELECTED_RIGHT, reinterpret_cast(push_button), data_1); +#endif + instance_data->m_state &= ~4; + return MSG_HANDLED; + } + case GWM_MOUSE_ENTERING: { + if ((instance_data->Get_Style() & GWS_MOUSE_TRACK) != 0) { + instance_data->m_state |= 2; +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + instance_data->Get_Owner(), GBM_MOUSE_ENTERING, reinterpret_cast(push_button), data_1); +#endif + } + + if (push_button->Win_Get_Parent() != nullptr) { + if ((push_button->Win_Get_Parent()->Win_Get_Style() & GWS_HORZ_SLIDER) != 0) { + push_button->Win_Get_Parent()->Win_Get_Instance_Data()->m_state |= 2; + } + } + + return MSG_HANDLED; + } + case GWM_MOUSE_LEAVING: { + if ((instance_data->Get_Style() & GWS_MOUSE_TRACK) != 0) { + instance_data->m_state &= ~2; +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + instance_data->Get_Owner(), GBM_MOUSE_LEAVING, reinterpret_cast(push_button), data_1); +#endif + } + + if ((push_button->Win_Get_Status() & WIN_STATUS_CHECK_LIKE) == 0 && (instance_data->Get_State() & 4) != 0) { + instance_data->m_state &= ~4; + } + + if (push_button->Win_Get_Parent() != nullptr) { + if ((push_button->Win_Get_Parent()->Win_Get_Style() & GWS_HORZ_SLIDER) != 0) { + push_button->Win_Get_Parent()->Win_Get_Instance_Data()->m_state &= ~2; + } + } + + return MSG_HANDLED; + } + case GWM_CHAR: { + switch (data_1) { + case Keyboard::KEY_TAB: + case Keyboard::KEY_RIGHT: + case Keyboard::KEY_DOWN: + if ((data_2 & 2) != 0) { + g_theWindowManager->Win_Next_Tab(push_button); + } + + return MSG_HANDLED; + case Keyboard::KEY_RETURN: + case Keyboard::KEY_SPACE: + if ((data_2 & 1) != 0) { + if ((instance_data->Get_State() & 4) != 0 + && (push_button->Win_Get_Status() & WIN_STATUS_CHECK_LIKE) == 0) { +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + instance_data->Get_Owner(), GBM_SELECTED, reinterpret_cast(push_button), 0); +#endif + instance_data->m_state &= ~4; + } + } else if ((push_button->Win_Get_Status() & WIN_STATUS_CHECK_LIKE) != 0) { + if ((instance_data->m_state & 4) != 0) { + instance_data->m_state &= ~4; + } else { + instance_data->m_state |= 4; + } + +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + instance_data->Get_Owner(), GBM_SELECTED, reinterpret_cast(push_button), data_1); +#endif + } else { + instance_data->m_state |= 4; + } + + return MSG_HANDLED; + case Keyboard::KEY_UP: + case Keyboard::KEY_LEFT: + if ((data_2 & Keyboard::KEY_STATE_DOWN) != 0) { + g_theWindowManager->Win_Prev_Tab(push_button); + } + + return MSG_HANDLED; + default: + return MSG_IGNORED; + } + } + default: + return MSG_IGNORED; + } } WindowMsgHandledType Gadget_Push_Button_System( GameWindow *push_button, unsigned int message, unsigned int data_1, unsigned int data_2) { -#ifdef GAME_DLL - return Call_Function( - PICK_ADDRESS(0x005AC1B0, 0x008F4D18), push_button, message, data_1, data_2); -#else - return MSG_IGNORED; -#endif + WinInstanceData *instance_data = push_button->Win_Get_Instance_Data(); + + if (message > GWM_INPUT_FOCUS) { + if (message != GGM_SET_LABEL) { + return MSG_IGNORED; + } + + push_button->Win_Set_Text(*reinterpret_cast(data_1)); + } else if (message == GWM_INPUT_FOCUS) { + if (data_1 != 0) { + instance_data->m_state = instance_data->m_state | 2; + } else { + instance_data->m_state = instance_data->m_state & ~2; + } + + g_theWindowManager->Win_Send_System_Msg( + instance_data->Get_Owner(), GGM_FOCUS_CHANGE, data_1, push_button->Win_Get_Window_Id()); + + if (data_1) { + *reinterpret_cast(data_2) = true; + } else { + *reinterpret_cast(data_2) = false; + } + } else if (message != GWM_CREATE) { + if (message != GWM_DESTROY) { + return MSG_IGNORED; + } + + _PushButtonData *data = static_cast<_PushButtonData *>(push_button->Win_Get_User_Data()); + + if (data != nullptr) { + delete data; + } + + push_button->Win_Set_User_Data(nullptr); + } + + return MSG_HANDLED; } -void *Gadget_Button_Get_Data(GameWindow *push_button) +void Gadget_Check_Like_Button_Set_Visual_Check(GameWindow *push_button, bool is_checked) { -#ifdef GAME_DLL - return Call_Function(PICK_ADDRESS(0x005AC4D0, 0x008F5209), push_button); -#else - return nullptr; -#endif + if (push_button != nullptr) { + WinInstanceData *instance_data = push_button->Win_Get_Instance_Data(); + + if (instance_data != nullptr) { + if ((push_button->Win_Get_Status() & WIN_STATUS_CHECK_LIKE) != 0) { + if ((instance_data->m_state & 4) != 0) { + instance_data->m_state &= ~4; + } else { + instance_data->m_state |= 4; + } + } else { + captainslog_dbgassert(false, "Gadget_Check_Like_Button_Set_Visual_Check: Window is not 'CHECK-LIKE'"); + } + } + } } void Gadget_Button_Enable_Check_Like(GameWindow *push_button, bool is_enabled, bool is_checked) { -#ifdef GAME_DLL - Call_Function(PICK_ADDRESS(0x005AC300, 0x008F4F1C), push_button, is_enabled, is_checked); -#endif + if (push_button != nullptr) { + WinInstanceData *instance_data = push_button->Win_Get_Instance_Data(); + + if (instance_data != nullptr) { + if (is_enabled) { + push_button->Win_Set_Status(WIN_STATUS_CHECK_LIKE); + } else { + push_button->Win_Clear_Status(WIN_STATUS_CHECK_LIKE); + } + + if (is_checked) { + instance_data->m_state = instance_data->m_state | 4; + } else { + instance_data->m_state = instance_data->m_state & ~4; + } + } + } } -void Gadget_Button_Set_Data(GameWindow *push_button, void *data) +void Gadget_Button_Set_Text(GameWindow *push_button, Utf16String text) { -#ifdef GAME_DLL - Call_Function(PICK_ADDRESS(0x005AC4A0, 0x008F51CB), push_button, data); +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg(push_button, GGM_SET_LABEL, reinterpret_cast(&text), 0); #endif } -void Gadget_Button_Set_Alt_Sound(GameWindow *push_button, Utf8String alt_sound) +_PushButtonData *Get_New_Push_Button_Data() { -#ifdef GAME_DLL - Call_Function(PICK_ADDRESS(0x005AC4F0, 0x008F5236), push_button, alt_sound); -#endif + _PushButtonData *data = new _PushButtonData(); + + if (data == nullptr) { + return nullptr; + } + + data->m_userData = nullptr; + data->m_drawBorder = false; + data->m_drawClock = false; + data->m_overlayImage = nullptr; + return data; } void Gadget_Button_Set_Border(GameWindow *push_button, int color, bool draw_border) { -#ifdef GAME_DLL - Call_Function(PICK_ADDRESS(0x005AC3F0, 0x008F50AC), push_button, color, draw_border); -#endif + if (push_button != nullptr) { + _PushButtonData *data = static_cast<_PushButtonData *>(push_button->Win_Get_User_Data()); + + if (data == nullptr) { + data = Get_New_Push_Button_Data(); + } + + data->m_drawBorder = draw_border; + data->m_colorBorder = color; + push_button->Win_Set_User_Data(data); + } +} + +void Gadget_Button_Draw_Inverse_Clock(GameWindow *push_button, int percent, int color) +{ + if (push_button != nullptr) { + _PushButtonData *data = static_cast<_PushButtonData *>(push_button->Win_Get_User_Data()); + + if (data == nullptr) { + data = Get_New_Push_Button_Data(); + } + + data->m_drawClock = 2; + data->m_percentClock = percent; + data->m_colorClock = color; + push_button->Win_Set_User_Data(data); + } } void Gadget_Button_Draw_Overlay_Image(GameWindow *push_button, const Image *image) { -#ifdef GAME_DLL - Call_Function(PICK_ADDRESS(0x005AC470, 0x008F518D), push_button, image); -#endif + if (push_button != nullptr) { + _PushButtonData *data = static_cast<_PushButtonData *>(push_button->Win_Get_User_Data()); + + if (data == nullptr) { + data = Get_New_Push_Button_Data(); + } + + data->m_overlayImage = image; + push_button->Win_Set_User_Data(data); + } } -void Gadget_Button_Draw_Inverse_Clock(GameWindow *push_button, int percent, int color) +void Gadget_Button_Set_Data(GameWindow *push_button, void *user_data) { -#ifdef GAME_DLL - Call_Function(PICK_ADDRESS(0x005AC430, 0x008F5140), push_button, percent, color); -#endif + if (push_button != nullptr) { + _PushButtonData *data = static_cast<_PushButtonData *>(push_button->Win_Get_User_Data()); + + if (data == nullptr) { + data = Get_New_Push_Button_Data(); + } + + data->m_userData = user_data; + push_button->Win_Set_User_Data(data); + } } -void Gadget_Check_Like_Button_Set_Visual_Check(GameWindow *push_button, bool is_checked) +void *Gadget_Button_Get_Data(GameWindow *push_button) { -#ifdef GAME_DLL - Call_Function(PICK_ADDRESS(0x005AC2B0, 0x008F4E41), push_button, is_checked); -#endif + if (push_button == nullptr) { + return nullptr; + } + + _PushButtonData *data = static_cast<_PushButtonData *>(push_button->Win_Get_User_Data()); + + if (data != nullptr) { + return data->m_userData; + } else { + return nullptr; + } +} + +void Gadget_Button_Set_Alt_Sound(GameWindow *push_button, Utf8String alt_sound) +{ + if (push_button != nullptr) { + _PushButtonData *data = static_cast<_PushButtonData *>(push_button->Win_Get_User_Data()); + + if (data != nullptr) { + data->m_altSound = alt_sound; + } + + push_button->Win_Set_User_Data(data); + } +} + +bool Gadget_Check_Like_Button_Is_Checked(GameWindow *push_button) +{ + if (push_button == nullptr) { + return false; + } + + WinInstanceData *instance_data = push_button->Win_Get_Instance_Data(); + return instance_data != nullptr && (instance_data->m_state & 4) != 0; +} + +void Gadget_Button_Draw_Clock(GameWindow *push_button, int percent, int color) +{ + if (push_button != nullptr) { + _PushButtonData *data = static_cast<_PushButtonData *>(push_button->Win_Get_User_Data()); + + if (data == nullptr) { + data = Get_New_Push_Button_Data(); + } + + data->m_drawClock = 1; + data->m_percentClock = percent; + data->m_colorClock = color; + push_button->Win_Set_User_Data(data); + } } diff --git a/src/game/client/gui/gadget/gadgetpushbutton.h b/src/game/client/gui/gadget/gadgetpushbutton.h index 98a8b9bd3..5cf46d520 100644 --- a/src/game/client/gui/gadget/gadgetpushbutton.h +++ b/src/game/client/gui/gadget/gadgetpushbutton.h @@ -16,6 +16,18 @@ #include "always.h" #include "gamewindow.h" +struct _PushButtonData +{ + char m_drawClock; + int m_percentClock; + int m_colorClock; + bool m_drawBorder; + int m_colorBorder; + void *m_userData; + const Image *m_overlayImage; + Utf8String m_altSound; +}; + inline void Gadget_Button_Set_Enabled_Image(GameWindow *push_button, const Image *image) { push_button->Win_Set_Enabled_Image(0, image); @@ -162,6 +174,6 @@ void Gadget_Button_Set_Border(GameWindow *push_button, int color, bool draw_bord void Gadget_Button_Draw_Clock(GameWindow *push_button, int percent, int color); void Gadget_Button_Draw_Inverse_Clock(GameWindow *push_button, int percent, int color); void Gadget_Button_Draw_Overlay_Image(GameWindow *push_button, const Image *image); -void Gadget_Button_Set_Data(GameWindow *push_button, void *data); +void Gadget_Button_Set_Data(GameWindow *push_button, void *user_data); void *Gadget_Button_Get_Data(GameWindow *push_button); void Gadget_Button_Set_Alt_Sound(GameWindow *push_button, Utf8String alt_sound); diff --git a/src/game/client/gui/gadget/gadgetradiobutton.cpp b/src/game/client/gui/gadget/gadgetradiobutton.cpp index 46e380dcd..9395aa0e2 100644 --- a/src/game/client/gui/gadget/gadgetradiobutton.cpp +++ b/src/game/client/gui/gadget/gadgetradiobutton.cpp @@ -15,12 +15,27 @@ #include "gadgetradiobutton.h" #include "gamewindowmanager.h" -void Gadget_Radio_Set_Text(GameWindow *radio_button, Utf16String text) +void Do_Radio_Unselect(GameWindow *radio_button, int group, int screen, GameWindow *except) { -#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a - // pointer to an unsigned int on 64 bit - g_theWindowManager->Win_Send_System_Msg(radio_button, GGM_SET_LABEL, reinterpret_cast(&text), 0); -#endif + if (radio_button != except && (radio_button->Win_Get_Style() & GWS_RADIO_BUTTON) != 0) { + _RadioButtonData *data = static_cast<_RadioButtonData *>(radio_button->Win_Get_User_Data()); + + if (data->m_group == group && data->m_screen == screen) { + radio_button->Win_Get_Instance_Data()->m_state &= ~4; + } + } + + for (GameWindow *child = radio_button->Win_Get_Child(); child != nullptr; child = child->Win_Get_Next()) { + Do_Radio_Unselect(child, group, screen, except); + } +} + +void Unselect_Other_Radio_Of_Group(int group, int screen, GameWindow *except) +{ + for (GameWindow *window = g_theWindowManager->Win_Get_Window_List(); window != nullptr; + window = window->Win_Get_Next()) { + Do_Radio_Unselect(window, group, screen, except); + } } WindowMsgHandledType Gadget_Radio_Button_Input( @@ -44,3 +59,29 @@ WindowMsgHandledType Gadget_Radio_Button_System( return MSG_IGNORED; #endif } + +void Gadget_Radio_Set_Text(GameWindow *radio_button, Utf16String text) +{ +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg(radio_button, GGM_SET_LABEL, reinterpret_cast(&text), 0); +#endif +} + +void Gadget_Radio_Set_Group(GameWindow *radio_button, int group, int screen) +{ + _RadioButtonData *data = static_cast<_RadioButtonData *>(radio_button->Win_Get_User_Data()); + data->m_group = group; + data->m_screen = screen; +} + +void Gadget_Radio_Set_Selection(GameWindow *radio_button, bool send_msg) +{ + if (radio_button != nullptr) { +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + radio_button, GBM_SET_SELECTION, reinterpret_cast(&send_msg), 0); +#endif + } +} diff --git a/src/game/client/gui/gadget/gadgetradiobutton.h b/src/game/client/gui/gadget/gadgetradiobutton.h index 877bb87f5..ebeff78a7 100644 --- a/src/game/client/gui/gadget/gadgetradiobutton.h +++ b/src/game/client/gui/gadget/gadgetradiobutton.h @@ -165,4 +165,4 @@ WindowMsgHandledType Gadget_Radio_Button_System( void Gadget_Radio_Set_Text(GameWindow *radio_button, Utf16String text); void Gadget_Radio_Set_Group(GameWindow *radio_button, int group, int screen); -void Gadget_Radio_Set_Selection(GameWindow *radio_button, int send_msg); +void Gadget_Radio_Set_Selection(GameWindow *radio_button, bool send_msg); diff --git a/src/game/client/gui/gadget/gadgettabcontrol.cpp b/src/game/client/gui/gadget/gadgettabcontrol.cpp index d3be02132..64d0cef24 100644 --- a/src/game/client/gui/gadget/gadgettabcontrol.cpp +++ b/src/game/client/gui/gadget/gadgettabcontrol.cpp @@ -13,52 +13,163 @@ * LICENSE */ #include "gadgettabcontrol.h" +#include "gamewindowmanager.h" -void Gadget_Tab_Control_Fixup_Sub_Pane_List(GameWindow *tab_control) +WindowMsgHandledType Gadget_Tab_Control_Input( + GameWindow *tab_control, unsigned int message, unsigned int data_1, unsigned int data_2) { - int i = 0; _TabControlData *tc_data = static_cast<_TabControlData *>(tab_control->Win_Get_User_Data()); - GameWindow *child = tab_control->Win_Get_Child(); + int x; + int y; + tab_control->Win_Get_Screen_Position(&x, &y); + int xpos = (data_1 & 0x0000FFFF) - x; + int ypos = ((data_1 & 0xFFFF0000) >> 16) - y; - if (child != nullptr) { - for (GameWindow *next = child->Win_Get_Next(); next != nullptr; next = child->Win_Get_Next()) { - child = child->Win_Get_Next(); + if (message == GWM_LEFT_DOWN) { + if (xpos < tc_data->m_tabsLeftLimit || xpos > tc_data->m_tabsRightLimit || ypos < tc_data->m_tabsTopLimit + || ypos > tc_data->m_tabsBottomLimit) { + return MSG_HANDLED; } - while (child != nullptr) { - tc_data->m_subPanes[i++] = child; - child = child->Win_Get_Prev(); + int i1; + int i2; + + if (tc_data->m_tabEdge == 4 || tc_data->m_tabEdge == 5) { + i1 = ypos - tc_data->m_tabsTopLimit; + i2 = tc_data->m_tabHeight; + } else { + i1 = xpos - tc_data->m_tabsLeftLimit; + i2 = tc_data->m_tabWidth; + } + + int which_pane = i1 / i2; + + if (!tc_data->m_subPaneDisabled[i1 / i2] && which_pane != tc_data->m_activeTab) { + Gadget_Tab_Control_Show_Sub_Pane(tab_control, which_pane); } } -} -WindowMsgHandledType Gadget_Tab_Control_Input( - GameWindow *tab_control, unsigned int message, unsigned int data_1, unsigned int data_2) -{ -#ifdef GAME_DLL - return Call_Function( - PICK_ADDRESS(0x006D7F60, 0x00A5A620), tab_control, message, data_1, data_2); -#else return MSG_IGNORED; -#endif } WindowMsgHandledType Gadget_Tab_Control_System( GameWindow *tab_control, unsigned int message, unsigned int data_1, unsigned int data_2) { -#ifdef GAME_DLL - return Call_Function( - PICK_ADDRESS(0x006D8070, 0x00A5A72F), tab_control, message, data_1, data_2); -#else - return MSG_IGNORED; -#endif + if (message > GGM_RESIZED) { + if (message == GBM_SELECTED) { + GameWindow *parent = tab_control->Win_Get_Parent(); + + if (parent != nullptr) { + return g_theWindowManager->Win_Send_System_Msg(parent, message, data_1, data_2); + } + } + + return MSG_IGNORED; + } + if (message == GGM_RESIZED) { + Gadget_Tab_Control_Resize_Sub_Panes(tab_control); + Gadget_Tab_Control_Compute_Tab_Region(tab_control); + } else if (message != GWM_CREATE) { + if (message != GWM_DESTROY) { + return MSG_IGNORED; + } + + _TabControlData *tc_data = static_cast<_TabControlData *>(tab_control->Win_Get_User_Data()); + delete tc_data; + } + + return MSG_HANDLED; } void Gadget_Tab_Control_Compute_Tab_Region(GameWindow *tab_control) { -#ifdef GAME_DLL - Call_Function(PICK_ADDRESS(0x006D8160, 0x00A5A7E4), tab_control); -#endif + int width; + int height; + tab_control->Win_Get_Size(&width, &height); + _TabControlData *tc_data = static_cast<_TabControlData *>(tab_control->Win_Get_User_Data()); + int i1 = 0; + int i2 = 0; + + if (tc_data->m_tabEdge == 3 || tc_data->m_tabEdge == 6) { + if (tc_data->m_tabOrientation != 0) { + if (tc_data->m_tabOrientation == 2) { + i1 = width - 2 * tc_data->m_paneBorder - tc_data->m_tabWidth * tc_data->m_tabCount; + } else if (tc_data->m_tabOrientation == 1) { + i1 = 0; + } + } else { + i1 = width - 2 * tc_data->m_paneBorder - tc_data->m_tabWidth * tc_data->m_tabCount; + i1 /= 2; + } + } else if (tc_data->m_tabOrientation != 0) { + if (tc_data->m_tabOrientation == 2) { + i2 = height - 2 * tc_data->m_paneBorder - tc_data->m_tabHeight * tc_data->m_tabCount; + } else if (tc_data->m_tabOrientation == 1) { + i2 = 0; + } + } else { + i2 = height - 2 * tc_data->m_paneBorder - tc_data->m_tabHeight * tc_data->m_tabCount; + i2 /= 2; + } + + switch (tc_data->m_tabEdge) { + case 3: + tc_data->m_tabsTopLimit = tc_data->m_paneBorder; + tc_data->m_tabsBottomLimit = tc_data->m_tabHeight + tc_data->m_paneBorder; + tc_data->m_tabsLeftLimit = i1 + tc_data->m_paneBorder; + tc_data->m_tabsRightLimit = tc_data->m_tabCount * tc_data->m_tabWidth + i1 + tc_data->m_paneBorder; + break; + case 6: + tc_data->m_tabsTopLimit = height - tc_data->m_paneBorder - tc_data->m_tabHeight; + tc_data->m_tabsBottomLimit = height - tc_data->m_paneBorder; + tc_data->m_tabsLeftLimit = i1 + tc_data->m_paneBorder; + tc_data->m_tabsRightLimit = tc_data->m_tabCount * tc_data->m_tabWidth + i1 + tc_data->m_paneBorder; + break; + case 4: + tc_data->m_tabsLeftLimit = width - tc_data->m_paneBorder - tc_data->m_tabWidth; + tc_data->m_tabsRightLimit = width - tc_data->m_paneBorder; + tc_data->m_tabsTopLimit = i2 + tc_data->m_paneBorder; + tc_data->m_tabsBottomLimit = tc_data->m_tabCount * tc_data->m_tabHeight + i2 + tc_data->m_paneBorder; + break; + case 5: + tc_data->m_tabsLeftLimit = tc_data->m_paneBorder; + tc_data->m_tabsRightLimit = tc_data->m_tabWidth + tc_data->m_paneBorder; + tc_data->m_tabsTopLimit = i2 + tc_data->m_paneBorder; + tc_data->m_tabsBottomLimit = tc_data->m_tabCount * tc_data->m_tabHeight + i2 + tc_data->m_paneBorder; + break; + } +} + +void Gadget_Tab_Control_Compute_Sub_Pane_Size(GameWindow *tab_control, int *width, int *height, int *x, int *y) +{ + int w; + int h; + tab_control->Win_Get_Size(&w, &h); + _TabControlData *tc_data = static_cast<_TabControlData *>(tab_control->Win_Get_User_Data()); + + if (tc_data->m_tabEdge == 3 || tc_data->m_tabEdge == 6) { + *height = h - 2 * tc_data->m_paneBorder - tc_data->m_tabHeight; + } else { + *height = h - 2 * tc_data->m_paneBorder; + } + + if (tc_data->m_tabEdge == 5 || tc_data->m_tabEdge == 4) { + *width = w - 2 * tc_data->m_paneBorder - tc_data->m_tabWidth; + } else { + *width = w - 2 * tc_data->m_paneBorder; + } + + if (tc_data->m_tabEdge == 5) { + *x = tc_data->m_tabWidth + tc_data->m_paneBorder; + } else { + *x = tc_data->m_paneBorder; + } + + if (tc_data->m_tabEdge == 3) { + *y = tc_data->m_tabHeight + tc_data->m_paneBorder; + } else { + *y = tc_data->m_paneBorder; + } } void Gadget_Tab_Control_Show_Sub_Pane(GameWindow *tab_control, int which_pane) @@ -83,7 +194,66 @@ void Gadget_Tab_Control_Show_Sub_Pane(GameWindow *tab_control, int which_pane) void Gadget_Tab_Control_Create_Sub_Panes(GameWindow *tab_control) { -#ifdef GAME_DLL - Call_Function(PICK_ADDRESS(0x006D83F0, 0x00A5ABFC), tab_control); -#endif + _TabControlData *tc_data = static_cast<_TabControlData *>(tab_control->Win_Get_User_Data()); + + int width; + int height; + int x; + int y; + Gadget_Tab_Control_Compute_Sub_Pane_Size(tab_control, &width, &height, &x, &y); + + for (int i = 0; i < NUM_TAB_PANES; i++) { + if (tc_data->m_subPanes[i] != nullptr) { + tc_data->m_subPanes[i]->Win_Set_Size(width, height); + tc_data->m_subPanes[i]->Win_Set_Position(x, y); + } else { + tc_data->m_subPanes[i] = g_theWindowManager->Win_Create( + tab_control, 0, x, y, width, height, Pass_Selected_Buttons_To_Parent_System, nullptr); + WinInstanceData *data = tc_data->m_subPanes[i]->Win_Get_Instance_Data(); + data->m_style |= GWS_TAB_PANE; + + char buf[20]; + sprintf(buf, "Pane %d", i); + data->m_decoratedNameString = buf; + tc_data->m_subPanes[i]->Win_Enable((tab_control->Win_Get_Status() & WIN_STATUS_ENABLED) != 0); + } + } + + Gadget_Tab_Control_Show_Sub_Pane(tab_control, tc_data->m_activeTab); +} + +void Gadget_Tab_Control_Resize_Sub_Panes(GameWindow *tab_control) +{ + _TabControlData *tc_data = static_cast<_TabControlData *>(tab_control->Win_Get_User_Data()); + + int width; + int height; + int x; + int y; + Gadget_Tab_Control_Compute_Sub_Pane_Size(tab_control, &width, &height, &x, &y); + + for (int i = 0; i < NUM_TAB_PANES; i++) { + if (tc_data->m_subPanes[i] != nullptr) { + tc_data->m_subPanes[i]->Win_Set_Size(width, height); + tc_data->m_subPanes[i]->Win_Set_Position(x, y); + } + } +} + +void Gadget_Tab_Control_Fixup_Sub_Pane_List(GameWindow *tab_control) +{ + int i = 0; + _TabControlData *tc_data = static_cast<_TabControlData *>(tab_control->Win_Get_User_Data()); + GameWindow *child = tab_control->Win_Get_Child(); + + if (child != nullptr) { + for (GameWindow *next = child->Win_Get_Next(); next != nullptr; next = child->Win_Get_Next()) { + child = child->Win_Get_Next(); + } + + while (child != nullptr) { + tc_data->m_subPanes[i++] = child; + child = child->Win_Get_Prev(); + } + } } diff --git a/src/game/client/gui/gadget/gadgettabcontrol.h b/src/game/client/gui/gadget/gadgettabcontrol.h index eefdb5c51..1a4e181be 100644 --- a/src/game/client/gui/gadget/gadgettabcontrol.h +++ b/src/game/client/gui/gadget/gadgettabcontrol.h @@ -45,8 +45,8 @@ WindowMsgHandledType Gadget_Tab_Control_System( GameWindow *tab_control, unsigned int message, unsigned int data_1, unsigned int data_2); void Gadget_Tab_Control_Compute_Tab_Region(GameWindow *tab_control); -void Gadget_Tab_Control_Compute_Sub_Pane_Size(GameWindow *tab_control, int width, int height, int x, int y); void Gadget_Tab_Control_Show_Sub_Pane(GameWindow *tab_control, int which_pane); void Gadget_Tab_Control_Create_Sub_Panes(GameWindow *tab_control); -void Gadget_Tab_Control_Resize_Sub_Panes(GameWindow *tab_control); void Gadget_Tab_Control_Fixup_Sub_Pane_List(GameWindow *tab_control); +void Gadget_Tab_Control_Compute_Sub_Pane_Size(GameWindow *tab_control, int *width, int *height, int *x, int *y); +void Gadget_Tab_Control_Resize_Sub_Panes(GameWindow *tab_control); diff --git a/src/game/client/gui/gadget/gadgettextentry.cpp b/src/game/client/gui/gadget/gadgettextentry.cpp index 5ac52371b..a176ac4b1 100644 --- a/src/game/client/gui/gadget/gadgettextentry.cpp +++ b/src/game/client/gui/gadget/gadgettextentry.cpp @@ -14,7 +14,10 @@ */ #include "gadgettextentry.h" #include "displaystring.h" +#include "displaystringmanager.h" #include "gamewindow.h" +#include "imemanager.h" +#include "keyboard.h" void Gadget_Text_Entry_Set_Font(GameWindow *text_entry, GameFont *font) { @@ -45,21 +48,236 @@ void Gadget_Text_Entry_Set_Font(GameWindow *text_entry, GameFont *font) WindowMsgHandledType Gadget_Text_Entry_Input( GameWindow *text_entry, unsigned int message, unsigned int data_1, unsigned int data_2) { -#ifdef GAME_DLL - return Call_Function( - PICK_ADDRESS(0x005CB380, 0x00A51AF0), text_entry, message, data_1, data_2); -#else - return MSG_IGNORED; + _EntryData *data = static_cast<_EntryData *>(text_entry->Win_Get_User_Data()); + WinInstanceData *instance_data = text_entry->Win_Get_Instance_Data(); + + if (g_theIMEManager != nullptr && g_theIMEManager->Is_Attached_To(text_entry) && g_theIMEManager->Is_Composing()) { + return MSG_HANDLED; + } + + switch (message) { + case GWM_LEFT_DOWN: + instance_data->m_state |= 2; + g_theWindowManager->Win_Set_Focus(text_entry); + return MSG_HANDLED; + case GWM_LEFT_DRAG: + if ((instance_data->Get_Style() & GWS_MOUSE_TRACK) != 0) { +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + instance_data->Get_Owner(), GGM_LEFT_DRAG, reinterpret_cast(text_entry), 0); +#endif + } + + return MSG_HANDLED; + case GWM_MOUSE_ENTERING: + if ((instance_data->Get_Style() & GWS_MOUSE_TRACK) != 0) { +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + instance_data->Get_Owner(), GBM_MOUSE_ENTERING, reinterpret_cast(text_entry), 0); +#endif + } + + return MSG_HANDLED; + case GWM_MOUSE_LEAVING: + if ((instance_data->Get_Style() & GWS_MOUSE_TRACK) != 0) { +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + instance_data->Get_Owner(), GBM_MOUSE_LEAVING, reinterpret_cast(text_entry), 0); +#endif + } + + return MSG_HANDLED; + case GWM_CHAR: + if ((data_2 & 2) != 0 && (data_2 & 0xCC) != 0) { + return MSG_IGNORED; + } + + switch (data_1) { + case Keyboard::KEY_ESCAPE: + case Keyboard::KEY_CAPITAL: + case Keyboard::KEY_F1: + case Keyboard::KEY_F2: + case Keyboard::KEY_F3: + case Keyboard::KEY_F4: + case Keyboard::KEY_F5: + case Keyboard::KEY_F6: + case Keyboard::KEY_F7: + case Keyboard::KEY_F8: + case Keyboard::KEY_F9: + case Keyboard::KEY_F10: + case Keyboard::KEY_F11: + case Keyboard::KEY_F12: + case Keyboard::KEY_HOME: + case Keyboard::KEY_PRIOR: + case Keyboard::KEY_END: + case Keyboard::KEY_NEXT: + case Keyboard::KEY_DELETE: + return MSG_IGNORED; + case Keyboard::KEY_BACK: + if ((data_2 & 2) != 0 && data->m_conCharPos == 0 && data->m_charPos != 0) { + data->m_text->Remove_Last_Char(); + data->m_sText->Remove_Last_Char(); + --data->m_charPos; +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + instance_data->Get_Owner(), GEM_UPDATE_TEXT, reinterpret_cast(text_entry), 0); +#endif + } + + return MSG_HANDLED; + case Keyboard::KEY_TAB: + case Keyboard::KEY_RIGHT: + case Keyboard::KEY_DOWN: + if ((data_2 & 2) != 0) { + GameWindow *parent = text_entry->Win_Get_Parent(); + + if (parent != nullptr && (parent->Win_Get_Style() & GWS_COMBO_BOX) == 0) { + parent = nullptr; + } + + if (parent) { + g_theWindowManager->Win_Next_Tab(parent); + } else { + g_theWindowManager->Win_Next_Tab(text_entry); + } + } + + return MSG_HANDLED; + case Keyboard::KEY_UP: + case Keyboard::KEY_LEFT: + if ((data_2 & 2) != 0) { + GameWindow *parent = text_entry->Win_Get_Parent(); + + if (parent != nullptr && (parent->Win_Get_Style() & GWS_COMBO_BOX) == 0) { + parent = nullptr; + } + + if (parent) { + g_theWindowManager->Win_Prev_Tab(parent); + } else { + g_theWindowManager->Win_Prev_Tab(text_entry); + } + } + + return MSG_HANDLED; + default: + return MSG_HANDLED; + } + case GWM_IME_CHAR: + if (static_cast(data_1) == U_CHAR('\r')) { +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + instance_data->Get_Owner(), GEM_EDIT_DONE, reinterpret_cast(text_entry), 0); +#endif + return MSG_HANDLED; + } + + if (static_cast(data_1) == U_CHAR('\0')) { + return MSG_HANDLED; + } + + if (!data->m_numericalOnly || g_theWindowManager->Win_Is_Digit(static_cast(data_1))) { + if (!data->m_alphaNumericalOnly || g_theWindowManager->Win_Is_Al_Num(static_cast(data_1))) { + if (!data->m_asciiOnly || g_theWindowManager->Win_Is_Ascii(static_cast(data_1))) { + if (data->m_charPos < data->m_maxTextLen - 1) { + data->m_text->Add_Char(static_cast(data_1)); + data->m_sText->Add_Char(U_CHAR('*')); + data->m_charPos++; + +#ifdef GAME_DLL // temporary since we can't change the definition of Win_Send_System_Msg at this point and we can't cast a + // pointer to an unsigned int on 64 bit + g_theWindowManager->Win_Send_System_Msg( + instance_data->Get_Owner(), GEM_UPDATE_TEXT, reinterpret_cast(text_entry), 0); #endif + } + + return MSG_HANDLED; + } else { + return MSG_HANDLED; + } + } else { + return MSG_HANDLED; + } + } else { + return MSG_HANDLED; + } + default: + return MSG_IGNORED; + } } WindowMsgHandledType Gadget_Text_Entry_System( GameWindow *text_entry, unsigned int message, unsigned int data_1, unsigned int data_2) { -#ifdef GAME_DLL - return Call_Function( - PICK_ADDRESS(0x005CB7C0, 0x00A520D2), text_entry, message, data_1, data_2); -#else - return MSG_IGNORED; -#endif + _EntryData *data = static_cast<_EntryData *>(text_entry->Win_Get_User_Data()); + WinInstanceData *instance_data = text_entry->Win_Get_Instance_Data(); + + if (message > GWM_INPUT_FOCUS) { + if (message == GEM_GET_TEXT) { + *reinterpret_cast(data_2) = data->m_text->Get_Text(); + } else { + if (message != GEM_SET_TEXT) { + return MSG_IGNORED; + } + + data->m_text->Set_Text(*reinterpret_cast(data_1)); + data->m_charPos = reinterpret_cast(data_1)->Get_Length(); + data->m_constructText->Set_Text(Utf16String::s_emptyString); + data->m_conCharPos = 0; + data->m_sText->Set_Text(Utf16String::s_emptyString); + int length = reinterpret_cast(data_1)->Get_Length(); + + for (int i = 0; i < length; i++) { + data->m_sText->Add_Char(U_CHAR('*')); + } + } + } else if (message == GWM_INPUT_FOCUS) { + if (data_1 != 0) { + if (g_theIMEManager != nullptr) { + g_theIMEManager->Attach(text_entry); + } + + instance_data->m_state |= 4; + instance_data->m_state |= 2; + } else { + instance_data->m_state &= ~4; + instance_data->m_state &= ~2; + + if (data->m_constructList != nullptr) { + data->m_constructList->Win_Hide(true); + } + + data->m_constructText->Set_Text(Utf16String::s_emptyString); + data->m_conCharPos = 0; + + if (g_theIMEManager != nullptr && g_theIMEManager->Is_Attached_To(text_entry)) { + g_theIMEManager->Attach(nullptr); + } + } + + g_theWindowManager->Win_Send_System_Msg( + instance_data->Get_Owner(), GGM_FOCUS_CHANGE, data_1, text_entry->Win_Get_Window_Id()); + *reinterpret_cast(data_2) = true; + } else if (message != GWM_CREATE) { + if (message != GWM_DESTROY) { + return MSG_IGNORED; + } + + g_theDisplayStringManager->Free_Display_String(data->m_text); + g_theDisplayStringManager->Free_Display_String(data->m_sText); + g_theDisplayStringManager->Free_Display_String(data->m_constructText); + + if (data->m_constructList != nullptr) { + g_theWindowManager->Win_Destroy(data->m_constructList); + } + + delete data; + } + + return MSG_HANDLED; } diff --git a/src/game/client/gui/gadget/gadgettextentry.h b/src/game/client/gui/gadget/gadgettextentry.h index 1baeedaea..aa056089b 100644 --- a/src/game/client/gui/gadget/gadgettextentry.h +++ b/src/game/client/gui/gadget/gadgettextentry.h @@ -30,8 +30,8 @@ struct _EntryData bool m_receivedUnichar; bool m_noInput; GameWindow *m_constructList; - short m_charPos; - short m_conCharPos; + unsigned short m_charPos; + unsigned short m_conCharPos; }; inline void Gadget_Text_Entry_Set_Enabled_Item_Left_End_Image(GameWindow *text_entry, const Image *image) diff --git a/src/game/common/system/unicodestring.cpp b/src/game/common/system/unicodestring.cpp index 0c1bdc283..590675eb7 100644 --- a/src/game/common/system/unicodestring.cpp +++ b/src/game/common/system/unicodestring.cpp @@ -362,7 +362,7 @@ void Utf16String::Remove_Last_Char() if (len > 0) { Ensure_Unique_Buffer_Of_Size(len + 1, true); - Peek()[len] = U_CHAR('\0'); + Peek()[len - 1] = U_CHAR('\0'); } } diff --git a/src/hooker/setuphooks_zh.cpp b/src/hooker/setuphooks_zh.cpp index e1553aeef..24b8dea5a 100644 --- a/src/hooker/setuphooks_zh.cpp +++ b/src/hooker/setuphooks_zh.cpp @@ -67,12 +67,15 @@ #include "framemetrics.h" #include "functionlexicon.h" #include "fxlist.h" +#include "gadgetcheckbox.h" #include "gadgetcombobox.h" #include "gadgetlistbox.h" #include "gadgetprogressbar.h" #include "gadgetpushbutton.h" +#include "gadgetradiobutton.h" #include "gadgetstatictext.h" #include "gadgettabcontrol.h" +#include "gadgettextentry.h" #include "gameclient.h" #include "gamelogic.h" #include "gamemath.h" @@ -3533,12 +3536,6 @@ void Setup_Hooks() Hook_Any(0x004FC9C0, GameWindowManager::Go_Go_Gadget_Static_Text); Hook_Any(0x004FCB60, GameWindowManager::Go_Go_Gadget_Text_Entry); - // Because some code checks if the input function for a push button is Gadget_Push_Button_Input or not, we need to make - // sure the checks point to our version, not the original. - Hook_Memory(0x009DF1E0, Gadget_Push_Button_Input); - Hook_Memory(0x0045FD27, Gadget_Push_Button_Input); - Hook_Memory(0x005AC723, Gadget_Push_Button_Input); - Hook_Any(0x004FCE70, GameWindowManager::Assign_Default_Gadget_Look); Hook_Any(0x004FFC40, GameWindowManager::Win_Text_Label_To_Text); Hook_Any(0x004FFD30, GameWindowManager::Get_Window_Under_Cursor); @@ -3553,41 +3550,6 @@ void Setup_Hooks() Hook_Any(0x00515450, GameWindowTransitionsHandler::Remove); Hook_Any(0x00515760, GameWindowTransitionsHandler::Is_Finished); - // gadgetcombobox.h - Hook_Any(0x005C4430, Gadget_Combo_Box_Set_Colors); - Hook_Any(0x00A538AF, Gadget_Combo_Box_Set_Is_Editable); - Hook_Any(0x005C4710, Gadget_Combo_Box_Set_Max_Chars); - Hook_Any(0x005C4730, Gadget_Combo_Box_Set_Max_Display); - - // gadgetlistbox.h - Hook_Any(0x005E76A0, Gadget_List_Box_Set_Colors); - Hook_Any(0x005E85C0, Gadget_List_Box_Set_Audio_Feedback); - Hook_Any(0x005E8540, Gadget_List_Box_Set_Top_Visible_Entry); - Hook_Function(0x005E83E0, static_cast(&Gadget_List_Box_Set_Selected)); - Hook_Any(0x005E8440, Gadget_List_Box_Set_Item_Data); - Hook_Any(0x005E8410, Gadget_List_Box_Reset); - Hook_Any(0x005E84F0, Gadget_List_Box_Get_Top_Visible_Entry); - Hook_Any(0x005E85E0, Gadget_List_Box_Get_Num_Columns); - Hook_Any(0x005E8600, Gadget_List_Box_Get_Column_Width); - Hook_Any(0x005E84D0, Gadget_List_Box_Get_Bottom_Visible_Entry); - Hook_Any(0x005E7B60, Gadget_List_Box_Add_Entry_Text); - Hook_Function(0x005E7D60, - static_cast(&Gadget_List_Box_Add_Entry_Image)); - Hook_Function(0x005E83B0, static_cast(&Gadget_List_Box_Set_Selected)); - - // gadgetprogressbar.h - Hook_Any(0x005A2C60, Gadget_Progress_Bar_System); - Hook_Any(0x005A2C90, Gadget_Progress_Bar_Set_Progress); - - // gadgetstatictext.h - Hook_Any(0x005A2CC0, Gadget_Static_Text_Input); - Hook_Any(0x005A2DF0, Gadget_Static_Text_System); - Hook_Any(0x005A2EF0, Gadget_Static_Text_Set_Text); - Hook_Any(0x005A2F60, Gadget_Static_Text_Get_Text); - - // gadgettabcontrol.h - Hook_Any(0x006D8390, Gadget_Tab_Control_Show_Sub_Pane); - // w3dprogressbar.h Hook_Any(0x007CB2F0, W3D_Gadget_Progress_Bar_Draw); Hook_Any(0x007CB520, W3D_Gadget_Progress_Bar_Image_Draw); @@ -3921,4 +3883,109 @@ void Setup_Hooks() // cratesystem.cpp Hook_Any(0x0049B940, CrateSystem::Find_Crate_Template); + + // gadgetcheckbox.h + Hook_Any(0x005C2F10, Gadget_Check_Box_Input); + Hook_Any(0x005C3210, Gadget_Check_Box_System); + Hook_Any(0x005C32C0, Gadget_Check_Box_Set_Text); + Hook_Any(0x005C3330, Gadget_Check_Box_Set_Checked); + Hook_Any(0x005C3380, Gadget_Check_Box_Toggle); + Hook_Any(0x005C33D0, Gadget_Check_Box_Is_Checked); + + // gadgetcombobox.h + Hook_Any(0x005C4430, Gadget_Combo_Box_Set_Colors); + Hook_Any(0x00A538AF, Gadget_Combo_Box_Set_Is_Editable); + Hook_Any(0x005C4710, Gadget_Combo_Box_Set_Max_Chars); + Hook_Any(0x005C4730, Gadget_Combo_Box_Set_Max_Display); + Hook_Any(0x005C4750, Gadget_Combo_Box_Get_Text); + Hook_Any(0x005C47B0, Gadget_Combo_Box_Set_Text); + Hook_Any(0x005C4820, Gadget_Combo_Box_Get_Edit_Box); + Hook_Any(0x005C4840, Gadget_Combo_Box_Add_Entry); + Hook_Any(0x005C48D0, Gadget_Combo_Box_Reset); + Hook_Any(0x005C4900, Gadget_Combo_Box_Hide_List); + Hook_Any(0x005C4930, Gadget_Combo_Box_Set_Font); + Hook_Any(0x005C49B0, Gadget_Combo_Box_Set_Enabled_Text_Colors); + Hook_Any(0x005C49F0, Gadget_Combo_Box_Set_Disabled_Text_Colors); + Hook_Any(0x005C4A30, Gadget_Combo_Box_Set_Hilite_Text_Colors); + Hook_Any(0x005C4A70, Gadget_Combo_Box_Set_IME_Composite_Text_Colors); + Hook_Any(0x005C4AB0, Gadget_Combo_Box_Get_Selected_Pos); + Hook_Any(0x005C4AE0, Gadget_Combo_Box_Set_Selected_Pos); + Hook_Any(0x005C4B10, Gadget_Combo_Box_Set_Item_Data); + Hook_Any(0x005C4B40, Gadget_Combo_Box_Get_Item_Data); + Hook_Any(0x005C4B80, Gadget_Combo_Box_Get_Length); + + // gadgetlistbox.h + Hook_Any(0x005E4F90, Gadget_List_Box_Get_Entry_Based_On_XY); + Hook_Any(0x005E76A0, Gadget_List_Box_Set_Colors); + Hook_Any(0x005E7A20, Gadget_List_Box_Get_Text); + Hook_Any(0x005E7A50, Gadget_List_Box_Get_Text_And_Color); + Hook_Any(0x005E7B60, Gadget_List_Box_Add_Entry_Text); + Hook_Function(0x005E7D60, + static_cast(&Gadget_List_Box_Add_Entry_Image)); + Hook_Function(0x005E7DD0, + static_cast(&Gadget_List_Box_Add_Entry_Image)); + Hook_Any(0x005E7E30, Gadget_List_Box_Set_Font); + Hook_Any(0x005E7EF0, Gadget_List_Box_Create_Scroll_Bar); + Hook_Any(0x005E8110, Gadget_List_Box_Set_List_Length); + Hook_Any(0x005E8340, Gadget_List_Box_Get_List_Length); + Hook_Any(0x005E8360, Gadget_List_Box_Get_Num_Entries); + Hook_Any(0x005E8380, Gadget_List_Box_Get_Selected); + Hook_Function(0x005E83B0, static_cast(&Gadget_List_Box_Set_Selected)); + Hook_Function(0x005E83E0, static_cast(&Gadget_List_Box_Set_Selected)); + Hook_Any(0x005E8410, Gadget_List_Box_Reset); + Hook_Any(0x005E8440, Gadget_List_Box_Set_Item_Data); + Hook_Any(0x005E8480, Gadget_List_Box_Get_Item_Data); + Hook_Any(0x005E84D0, Gadget_List_Box_Get_Bottom_Visible_Entry); + Hook_Any(0x005E84F0, Gadget_List_Box_Get_Top_Visible_Entry); + Hook_Any(0x005E8540, Gadget_List_Box_Set_Top_Visible_Entry); + Hook_Any(0x005E85C0, Gadget_List_Box_Set_Audio_Feedback); + Hook_Any(0x005E85E0, Gadget_List_Box_Get_Num_Columns); + Hook_Any(0x005E8600, Gadget_List_Box_Get_Column_Width); + + // gadgetprogressbar.h + Hook_Any(0x005A2C60, Gadget_Progress_Bar_System); + Hook_Any(0x005A2C90, Gadget_Progress_Bar_Set_Progress); + + // gadgetpushbutton.h + // Because some code checks if the input function for a push button is Gadget_Push_Button_Input or not, we need to make + // sure the checks point to our version, not the original. + Hook_Memory(0x009DF1E0, Gadget_Push_Button_Input); + Hook_Memory(0x0045FD27, Gadget_Push_Button_Input); + Hook_Memory(0x005AC723, Gadget_Push_Button_Input); + // Hook_Any(0x005ABB40, Gadget_Push_Button_Input); + Hook_Any(0x005AC1B0, Gadget_Push_Button_System); + Hook_Any(0x005AC2B0, Gadget_Check_Like_Button_Set_Visual_Check); + Hook_Any(0x005AC300, Gadget_Button_Enable_Check_Like); + Hook_Any(0x005AC350, Gadget_Button_Set_Text); + Hook_Any(0x005AC3F0, Gadget_Button_Set_Border); + Hook_Any(0x005AC430, Gadget_Button_Draw_Inverse_Clock); + Hook_Any(0x005AC470, Gadget_Button_Draw_Overlay_Image); + Hook_Any(0x005AC4A0, Gadget_Button_Set_Data); + Hook_Any(0x005AC4D0, Gadget_Button_Get_Data); + Hook_Any(0x005AC4F0, Gadget_Button_Set_Alt_Sound); + + // gadgetradiobutton.h + Hook_Any(0x006D8C50, Gadget_Radio_Set_Text); + Hook_Any(0x006D8CC0, Gadget_Radio_Set_Selection); + + // gadgetstatictext.h + Hook_Any(0x005A2CC0, Gadget_Static_Text_Input); + Hook_Any(0x005A2DF0, Gadget_Static_Text_System); + Hook_Any(0x005A2EF0, Gadget_Static_Text_Set_Text); + Hook_Any(0x005A2F60, Gadget_Static_Text_Get_Text); + Hook_Any(0x005A2FB0, Gadget_Static_Text_Set_Font); + + // gadgettabcontrol.h + Hook_Any(0x006D7F60, Gadget_Tab_Control_Input); + Hook_Any(0x006D8070, Gadget_Tab_Control_System); + Hook_Any(0x006D8160, Gadget_Tab_Control_Compute_Tab_Region); + Hook_Any(0x006D82D0, Gadget_Tab_Control_Compute_Sub_Pane_Size); + Hook_Any(0x006D8390, Gadget_Tab_Control_Show_Sub_Pane); + Hook_Any(0x006D83F0, Gadget_Tab_Control_Create_Sub_Panes); + Hook_Any(0x006D85B0, Gadget_Tab_Control_Fixup_Sub_Pane_List); + + // gadgettextentry.h + Hook_Any(0x005CB380, Gadget_Text_Entry_Input); + Hook_Any(0x005CB7C0, Gadget_Text_Entry_System); + Hook_Any(0x005CBA20, Gadget_Text_Entry_Set_Font); }