2022-05-19 01:51:26 -07:00
|
|
|
#include "window_manager.h"
|
|
|
|
|
2022-09-15 02:38:23 -07:00
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
#include <SDL.h>
|
|
|
|
|
2022-05-19 01:51:26 -07:00
|
|
|
#include "color.h"
|
|
|
|
#include "debug.h"
|
2022-10-04 23:54:46 -07:00
|
|
|
#include "dinput.h"
|
2022-05-19 01:51:26 -07:00
|
|
|
#include "draw.h"
|
2022-10-04 23:23:27 -07:00
|
|
|
#include "input.h"
|
2022-05-19 01:51:26 -07:00
|
|
|
#include "memory.h"
|
2022-10-03 02:41:33 -07:00
|
|
|
#include "mouse.h"
|
2022-07-05 01:00:55 -07:00
|
|
|
#include "palette.h"
|
|
|
|
#include "pointer_registry.h"
|
2022-10-05 00:35:05 -07:00
|
|
|
#include "svga.h"
|
2022-05-19 01:51:26 -07:00
|
|
|
#include "text_font.h"
|
2022-10-02 23:37:05 -07:00
|
|
|
#include "vcr.h"
|
2022-05-28 11:46:58 -07:00
|
|
|
#include "win32.h"
|
2022-05-19 01:51:26 -07:00
|
|
|
#include "window_manager_private.h"
|
|
|
|
|
2022-09-23 05:43:44 -07:00
|
|
|
namespace fallout {
|
|
|
|
|
2022-07-04 23:21:26 -07:00
|
|
|
#define MAX_WINDOW_COUNT (50)
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
// The maximum number of button groups.
|
|
|
|
#define BUTTON_GROUP_LIST_CAPACITY (64)
|
2022-07-04 23:21:26 -07:00
|
|
|
|
|
|
|
static void windowFree(int win);
|
|
|
|
static void _win_buffering(bool a1);
|
|
|
|
static void _win_move(int win_index, int x, int y);
|
|
|
|
static void _win_clip(Window* window, RectListNode** rect, unsigned char* a3);
|
2023-07-20 00:20:05 -07:00
|
|
|
static void win_drag(int win);
|
2022-07-04 23:21:26 -07:00
|
|
|
static void _refresh_all(Rect* rect, unsigned char* a2);
|
|
|
|
static Button* buttonGetButton(int btn, Window** out_win);
|
|
|
|
static int paletteOpenFileImpl(const char* path, int flags);
|
|
|
|
static int paletteReadFileImpl(int fd, void* buf, size_t count);
|
|
|
|
static int paletteCloseFileImpl(int fd);
|
|
|
|
static Button* buttonCreateInternal(int win, int x, int y, int width, int height, int mouseEnterEventCode, int mouseExitEventCode, int mouseDownEventCode, int mouseUpEventCode, int flags, unsigned char* up, unsigned char* dn, unsigned char* hover);
|
2023-04-10 23:01:14 -07:00
|
|
|
static int _GNW_check_buttons(Window* window, int* keyCodePtr);
|
2022-07-04 23:21:26 -07:00
|
|
|
static bool _button_under_mouse(Button* button, Rect* rect);
|
|
|
|
static void buttonFree(Button* ptr);
|
2022-09-01 08:41:37 -07:00
|
|
|
static int button_new_id();
|
2023-04-10 23:01:14 -07:00
|
|
|
static int _win_group_check_buttons(int buttonCount, int* btns, int maxChecked, RadioButtonCallback* func);
|
2022-07-04 23:21:26 -07:00
|
|
|
static int _button_check_group(Button* button);
|
2023-04-10 23:01:14 -07:00
|
|
|
static void _button_draw(Button* button, Window* window, unsigned char* data, bool draw, Rect* bound, bool sound);
|
2022-07-04 23:21:26 -07:00
|
|
|
static void _GNW_button_refresh(Window* window, Rect* rect);
|
|
|
|
|
2022-05-19 01:51:26 -07:00
|
|
|
// 0x50FA30
|
2022-07-04 23:21:26 -07:00
|
|
|
static char _path_patches[] = "";
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x51E3D8
|
2022-07-04 23:21:26 -07:00
|
|
|
static bool _GNW95_already_running = false;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2022-05-29 12:08:13 -07:00
|
|
|
#ifdef _WIN32
|
2022-05-19 01:51:26 -07:00
|
|
|
// 0x51E3DC
|
2022-07-04 23:21:26 -07:00
|
|
|
static HANDLE _GNW95_title_mutex = INVALID_HANDLE_VALUE;
|
2022-05-29 12:08:13 -07:00
|
|
|
#endif
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x51E3E0
|
|
|
|
bool gWindowSystemInitialized = false;
|
|
|
|
|
|
|
|
// 0x51E3E4
|
2022-07-29 06:04:05 -07:00
|
|
|
int _GNW_wcolor[6] = {
|
2022-05-19 01:51:26 -07:00
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
|
|
|
// 0x51E3FC
|
2022-07-04 23:21:26 -07:00
|
|
|
static unsigned char* _screen_buffer = NULL;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x51E400
|
2022-07-04 23:21:26 -07:00
|
|
|
static bool _insideWinExit = false;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x51E404
|
2022-07-04 23:21:26 -07:00
|
|
|
static int _last_button_winID = -1;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x6ADD90
|
2022-12-12 23:18:02 -08:00
|
|
|
static int gWindowIndexes[MAX_WINDOW_COUNT];
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x6ADE58
|
2022-07-04 23:21:26 -07:00
|
|
|
static Window* gWindows[MAX_WINDOW_COUNT];
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x6ADF20
|
2022-07-04 23:21:26 -07:00
|
|
|
static VideoSystemExitProc* gVideoSystemExitProc;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x6ADF24
|
2022-07-04 23:21:26 -07:00
|
|
|
static int gWindowsLength;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x6ADF28
|
2022-07-04 23:21:26 -07:00
|
|
|
static int _window_flags;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x6ADF2C
|
2022-07-04 23:21:26 -07:00
|
|
|
static bool _buffering;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x6ADF30
|
2022-07-04 23:21:26 -07:00
|
|
|
static int _bk_color;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x6ADF34
|
2022-07-04 23:21:26 -07:00
|
|
|
static VideoSystemInitProc* gVideoSystemInitProc;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x6ADF38
|
2022-07-04 23:21:26 -07:00
|
|
|
static int _doing_refresh_all;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x6ADF3C
|
2022-07-04 23:21:26 -07:00
|
|
|
static void* _GNW_texture;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x6ADF40
|
2023-04-10 23:01:14 -07:00
|
|
|
static ButtonGroup gButtonGroups[BUTTON_GROUP_LIST_CAPACITY];
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
// 0x4D5C30
|
|
|
|
int windowManagerInit(VideoSystemInitProc* videoSystemInitProc, VideoSystemExitProc* videoSystemExitProc, int a3)
|
|
|
|
{
|
2022-05-29 12:08:13 -07:00
|
|
|
#ifdef _WIN32
|
2022-05-19 01:51:26 -07:00
|
|
|
CloseHandle(_GNW95_mutex);
|
|
|
|
_GNW95_mutex = INVALID_HANDLE_VALUE;
|
2022-05-29 12:08:13 -07:00
|
|
|
#endif
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
if (_GNW95_already_running) {
|
|
|
|
return WINDOW_MANAGER_ERR_ALREADY_RUNNING;
|
|
|
|
}
|
|
|
|
|
2022-05-29 12:08:13 -07:00
|
|
|
#ifdef _WIN32
|
2022-05-19 01:51:26 -07:00
|
|
|
if (_GNW95_title_mutex == INVALID_HANDLE_VALUE) {
|
|
|
|
return WINDOW_MANAGER_ERR_TITLE_NOT_SET;
|
|
|
|
}
|
2022-05-29 12:08:13 -07:00
|
|
|
#endif
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
if (gWindowSystemInitialized) {
|
|
|
|
return WINDOW_MANAGER_ERR_WINDOW_SYSTEM_ALREADY_INITIALIZED;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int index = 0; index < MAX_WINDOW_COUNT; index++) {
|
2022-12-12 23:18:02 -08:00
|
|
|
gWindowIndexes[index] = -1;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2022-08-16 01:25:56 -07:00
|
|
|
if (_db_total() == 0) {
|
2022-05-19 01:51:26 -07:00
|
|
|
if (dbOpen(NULL, 0, _path_patches, 1) == -1) {
|
|
|
|
return WINDOW_MANAGER_ERR_INITIALIZING_DEFAULT_DATABASE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (textFontsInit() == -1) {
|
|
|
|
return WINDOW_MANAGER_ERR_INITIALIZING_TEXT_FONTS;
|
|
|
|
}
|
|
|
|
|
|
|
|
_get_start_mode_();
|
|
|
|
|
|
|
|
gVideoSystemInitProc = videoSystemInitProc;
|
|
|
|
gVideoSystemExitProc = directInputFree;
|
|
|
|
|
|
|
|
int rc = videoSystemInitProc();
|
|
|
|
if (rc == -1) {
|
|
|
|
if (gVideoSystemExitProc != NULL) {
|
|
|
|
gVideoSystemExitProc();
|
|
|
|
}
|
|
|
|
|
|
|
|
return WINDOW_MANAGER_ERR_INITIALIZING_VIDEO_MODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rc == 8) {
|
|
|
|
return WINDOW_MANAGER_ERR_8;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a3 & 1) {
|
2022-05-21 08:22:03 -07:00
|
|
|
_screen_buffer = (unsigned char*)internal_malloc((_scr_size.bottom - _scr_size.top + 1) * (_scr_size.right - _scr_size.left + 1));
|
2022-05-19 01:51:26 -07:00
|
|
|
if (_screen_buffer == NULL) {
|
|
|
|
if (gVideoSystemExitProc != NULL) {
|
|
|
|
gVideoSystemExitProc();
|
|
|
|
} else {
|
|
|
|
directDrawFree();
|
|
|
|
}
|
|
|
|
|
|
|
|
return WINDOW_MANAGER_ERR_NO_MEMORY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_buffering = false;
|
|
|
|
_doing_refresh_all = 0;
|
|
|
|
|
|
|
|
colorPaletteSetFileIO(paletteOpenFileImpl, paletteReadFileImpl, paletteCloseFileImpl);
|
|
|
|
colorPaletteSetMemoryProcs(internal_malloc, internal_realloc, internal_free);
|
|
|
|
|
|
|
|
if (!_initColors()) {
|
2022-05-21 08:22:03 -07:00
|
|
|
unsigned char* palette = (unsigned char*)internal_malloc(768);
|
2022-05-19 01:51:26 -07:00
|
|
|
if (palette == NULL) {
|
|
|
|
if (gVideoSystemExitProc != NULL) {
|
|
|
|
gVideoSystemExitProc();
|
|
|
|
} else {
|
|
|
|
directDrawFree();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_screen_buffer != NULL) {
|
|
|
|
internal_free(_screen_buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
return WINDOW_MANAGER_ERR_NO_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
bufferFill(palette, 768, 1, 768, 0);
|
|
|
|
|
|
|
|
// TODO: Incomplete.
|
|
|
|
// _colorBuildColorTable(_getSystemPalette(), palette);
|
|
|
|
|
|
|
|
internal_free(palette);
|
|
|
|
}
|
|
|
|
|
|
|
|
_GNW_debug_init();
|
|
|
|
|
2022-10-05 00:11:47 -07:00
|
|
|
if (inputInit(a3) == -1) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return WINDOW_MANAGER_ERR_INITIALIZING_INPUT;
|
|
|
|
}
|
|
|
|
|
|
|
|
_GNW_intr_init();
|
|
|
|
|
2022-05-21 08:22:03 -07:00
|
|
|
Window* window = gWindows[0] = (Window*)internal_malloc(sizeof(*window));
|
2022-05-19 01:51:26 -07:00
|
|
|
if (window == NULL) {
|
|
|
|
if (gVideoSystemExitProc != NULL) {
|
|
|
|
gVideoSystemExitProc();
|
|
|
|
} else {
|
|
|
|
directDrawFree();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_screen_buffer != NULL) {
|
|
|
|
internal_free(_screen_buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
return WINDOW_MANAGER_ERR_NO_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
window->id = 0;
|
|
|
|
window->flags = 0;
|
|
|
|
window->rect.left = _scr_size.left;
|
|
|
|
window->rect.top = _scr_size.top;
|
|
|
|
window->rect.right = _scr_size.right;
|
|
|
|
window->rect.bottom = _scr_size.bottom;
|
|
|
|
window->width = _scr_size.right - _scr_size.left + 1;
|
|
|
|
window->height = _scr_size.bottom - _scr_size.top + 1;
|
2022-12-07 05:39:30 -08:00
|
|
|
window->tx = 0;
|
|
|
|
window->ty = 0;
|
2022-05-19 01:51:26 -07:00
|
|
|
window->buffer = NULL;
|
|
|
|
window->buttonListHead = NULL;
|
2022-12-07 05:39:30 -08:00
|
|
|
window->hoveredButton = NULL;
|
|
|
|
window->clickedButton = 0;
|
2022-07-29 06:04:05 -07:00
|
|
|
window->menuBar = NULL;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
gWindowsLength = 1;
|
|
|
|
gWindowSystemInitialized = 1;
|
|
|
|
_GNW_wcolor[3] = 21140;
|
|
|
|
_GNW_wcolor[4] = 32747;
|
|
|
|
_GNW_wcolor[5] = 31744;
|
2022-12-12 23:18:02 -08:00
|
|
|
gWindowIndexes[0] = 0;
|
2022-05-19 01:51:26 -07:00
|
|
|
_GNW_texture = NULL;
|
|
|
|
_bk_color = 0;
|
|
|
|
_GNW_wcolor[0] = 10570;
|
|
|
|
_window_flags = a3;
|
|
|
|
_GNW_wcolor[2] = 8456;
|
|
|
|
_GNW_wcolor[1] = 15855;
|
|
|
|
|
|
|
|
atexit(windowManagerExit);
|
|
|
|
|
|
|
|
return WINDOW_MANAGER_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D616C
|
|
|
|
void windowManagerExit(void)
|
|
|
|
{
|
|
|
|
if (!_insideWinExit) {
|
|
|
|
_insideWinExit = true;
|
|
|
|
if (gWindowSystemInitialized) {
|
|
|
|
_GNW_intr_exit();
|
|
|
|
|
|
|
|
for (int index = gWindowsLength - 1; index >= 0; index--) {
|
|
|
|
windowFree(gWindows[index]->id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_GNW_texture != NULL) {
|
|
|
|
internal_free(_GNW_texture);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_screen_buffer != NULL) {
|
|
|
|
internal_free(_screen_buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gVideoSystemExitProc != NULL) {
|
|
|
|
gVideoSystemExitProc();
|
|
|
|
}
|
|
|
|
|
2022-10-05 00:11:47 -07:00
|
|
|
inputExit();
|
2022-05-19 01:51:26 -07:00
|
|
|
_GNW_rect_exit();
|
|
|
|
textFontsExit();
|
|
|
|
_colorsClose();
|
|
|
|
|
2022-06-05 13:21:28 -07:00
|
|
|
SDL_DestroyWindow(gSdlWindow);
|
|
|
|
|
2022-05-19 01:51:26 -07:00
|
|
|
gWindowSystemInitialized = false;
|
|
|
|
|
2022-05-29 12:08:13 -07:00
|
|
|
#ifdef _WIN32
|
2022-05-19 01:51:26 -07:00
|
|
|
CloseHandle(_GNW95_title_mutex);
|
|
|
|
_GNW95_title_mutex = INVALID_HANDLE_VALUE;
|
2022-05-29 12:08:13 -07:00
|
|
|
#endif
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
_insideWinExit = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// win_add
|
|
|
|
// 0x4D6238
|
2022-12-07 05:39:30 -08:00
|
|
|
int windowCreate(int x, int y, int width, int height, int color, int flags)
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
int v23;
|
|
|
|
int v25, v26;
|
|
|
|
Window* tmp;
|
|
|
|
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gWindowsLength == MAX_WINDOW_COUNT) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (width > rectGetWidth(&_scr_size)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (height > rectGetHeight(&_scr_size)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-05-21 08:22:03 -07:00
|
|
|
Window* window = gWindows[gWindowsLength] = (Window*)internal_malloc(sizeof(*window));
|
2022-05-19 01:51:26 -07:00
|
|
|
if (window == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-05-21 08:22:03 -07:00
|
|
|
window->buffer = (unsigned char*)internal_malloc(width * height);
|
2022-05-19 01:51:26 -07:00
|
|
|
if (window->buffer == NULL) {
|
|
|
|
internal_free(window);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-12-12 23:18:02 -08:00
|
|
|
int id = 1;
|
|
|
|
while (windowGetWindow(id) != NULL) {
|
|
|
|
id++;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2022-12-12 23:18:02 -08:00
|
|
|
window->id = id;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2022-12-12 23:04:05 -08:00
|
|
|
if ((flags & WINDOW_USE_DEFAULTS) != 0) {
|
2022-05-19 01:51:26 -07:00
|
|
|
flags |= _window_flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
window->width = width;
|
|
|
|
window->height = height;
|
|
|
|
window->flags = flags;
|
2022-12-07 05:39:30 -08:00
|
|
|
window->tx = rand() & 0xFFFE;
|
|
|
|
window->ty = rand() & 0xFFFE;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
if (color == 256) {
|
2022-05-19 01:51:26 -07:00
|
|
|
if (_GNW_texture == NULL) {
|
2022-12-07 05:39:30 -08:00
|
|
|
color = _colorTable[_GNW_wcolor[0]];
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
2022-12-07 05:39:30 -08:00
|
|
|
} else if ((color & 0xFF00) != 0) {
|
|
|
|
int colorIndex = (color & 0xFF) - 1;
|
|
|
|
color = (color & ~0xFFFF) | _colorTable[_GNW_wcolor[colorIndex]];
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
window->buttonListHead = NULL;
|
|
|
|
window->hoveredButton = NULL;
|
|
|
|
window->clickedButton = NULL;
|
2022-07-29 06:04:05 -07:00
|
|
|
window->menuBar = NULL;
|
2022-05-19 01:51:26 -07:00
|
|
|
window->blitProc = blitBufferToBufferTrans;
|
2022-12-07 05:39:30 -08:00
|
|
|
window->color = color;
|
2022-12-12 23:18:02 -08:00
|
|
|
gWindowIndexes[id] = gWindowsLength;
|
2022-05-19 01:51:26 -07:00
|
|
|
gWindowsLength++;
|
|
|
|
|
2022-12-12 23:18:02 -08:00
|
|
|
windowFill(id, 0, 0, width, height, color);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
window->flags |= WINDOW_HIDDEN;
|
2022-12-12 23:18:02 -08:00
|
|
|
_win_move(id, x, y);
|
2022-05-19 01:51:26 -07:00
|
|
|
window->flags = flags;
|
|
|
|
|
2022-12-12 23:04:05 -08:00
|
|
|
if ((flags & WINDOW_MOVE_ON_TOP) == 0) {
|
2022-05-19 01:51:26 -07:00
|
|
|
v23 = gWindowsLength - 2;
|
|
|
|
while (v23 > 0) {
|
2022-12-12 23:04:05 -08:00
|
|
|
if (!(gWindows[v23]->flags & WINDOW_MOVE_ON_TOP)) {
|
2022-05-19 01:51:26 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
v23--;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (v23 != gWindowsLength - 2) {
|
|
|
|
v25 = v23 + 1;
|
|
|
|
v26 = gWindowsLength - 1;
|
|
|
|
while (v26 > v25) {
|
|
|
|
tmp = gWindows[v26 - 1];
|
|
|
|
gWindows[v26] = tmp;
|
2022-12-12 23:18:02 -08:00
|
|
|
gWindowIndexes[tmp->id] = v26;
|
2022-05-19 01:51:26 -07:00
|
|
|
v26--;
|
|
|
|
}
|
|
|
|
|
|
|
|
gWindows[v25] = window;
|
2022-12-12 23:18:02 -08:00
|
|
|
gWindowIndexes[id] = v25;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-12 23:18:02 -08:00
|
|
|
return id;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// win_remove
|
|
|
|
// 0x4D6468
|
|
|
|
void windowDestroy(int win)
|
|
|
|
{
|
|
|
|
Window* window = windowGetWindow(win);
|
|
|
|
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (window == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Rect rect;
|
|
|
|
rectCopy(&rect, &(window->rect));
|
|
|
|
|
2022-12-12 23:18:02 -08:00
|
|
|
int v1 = gWindowIndexes[window->id];
|
2022-05-19 01:51:26 -07:00
|
|
|
windowFree(win);
|
|
|
|
|
2022-12-12 23:18:02 -08:00
|
|
|
gWindowIndexes[win] = -1;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
for (int index = v1; index < gWindowsLength - 1; index++) {
|
|
|
|
gWindows[index] = gWindows[index + 1];
|
2022-12-12 23:18:02 -08:00
|
|
|
gWindowIndexes[gWindows[index]->id] = index;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
gWindowsLength--;
|
|
|
|
|
|
|
|
// NOTE: Uninline.
|
|
|
|
windowRefreshAll(&rect);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D650C
|
|
|
|
void windowFree(int win)
|
|
|
|
{
|
|
|
|
Window* window = windowGetWindow(win);
|
|
|
|
if (window == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (window->buffer != NULL) {
|
|
|
|
internal_free(window->buffer);
|
|
|
|
}
|
|
|
|
|
2022-07-29 06:04:05 -07:00
|
|
|
if (window->menuBar != NULL) {
|
|
|
|
internal_free(window->menuBar);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Button* curr = window->buttonListHead;
|
|
|
|
while (curr != NULL) {
|
|
|
|
Button* next = curr->next;
|
|
|
|
buttonFree(curr);
|
|
|
|
curr = next;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal_free(window);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D6558
|
|
|
|
void _win_buffering(bool a1)
|
|
|
|
{
|
|
|
|
if (_screen_buffer != NULL) {
|
|
|
|
_buffering = a1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D6568
|
|
|
|
void windowDrawBorder(int win)
|
|
|
|
{
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Window* window = windowGetWindow(win);
|
|
|
|
if (window == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_lighten_buf(window->buffer + 5, window->width - 10, 5, window->width);
|
|
|
|
_lighten_buf(window->buffer, 5, window->height, window->width);
|
|
|
|
_lighten_buf(window->buffer + window->width - 5, 5, window->height, window->width);
|
|
|
|
_lighten_buf(window->buffer + window->width * (window->height - 5) + 5, window->width - 10, 5, window->width);
|
|
|
|
|
|
|
|
bufferDrawRect(window->buffer, window->width, 0, 0, window->width - 1, window->height - 1, _colorTable[0]);
|
|
|
|
|
|
|
|
bufferDrawRectShadowed(window->buffer, window->width, 1, 1, window->width - 2, window->height - 2, _colorTable[_GNW_wcolor[1]], _colorTable[_GNW_wcolor[2]]);
|
|
|
|
bufferDrawRectShadowed(window->buffer, window->width, 5, 5, window->width - 6, window->height - 6, _colorTable[_GNW_wcolor[2]], _colorTable[_GNW_wcolor[1]]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D684C
|
2023-04-10 23:01:14 -07:00
|
|
|
void windowDrawText(int win, const char* str, int width, int x, int y, int color)
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
unsigned char* buf;
|
2023-04-10 23:01:14 -07:00
|
|
|
int textColor;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
Window* window = windowGetWindow(win);
|
|
|
|
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (window == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if (width == 0) {
|
|
|
|
if (color & 0x040000) {
|
|
|
|
width = fontGetMonospacedStringWidth(str);
|
2022-05-19 01:51:26 -07:00
|
|
|
} else {
|
2023-04-10 23:01:14 -07:00
|
|
|
width = fontGetStringWidth(str);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if (width + x > window->width) {
|
|
|
|
if (!(color & 0x04000000)) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
width = window->width - x;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
buf = window->buffer + x + y * window->width;
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if (fontGetLineHeight() + y > window->height) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if (!(color & 0x02000000)) {
|
2022-12-07 05:39:30 -08:00
|
|
|
if (window->color == 256 && _GNW_texture != NULL) {
|
2023-04-10 23:01:14 -07:00
|
|
|
_buf_texture(buf, width, fontGetLineHeight(), window->width, _GNW_texture, window->tx + x, window->ty + y);
|
2022-05-19 01:51:26 -07:00
|
|
|
} else {
|
2023-04-10 23:01:14 -07:00
|
|
|
bufferFill(buf, width, fontGetLineHeight(), window->width, window->color);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-19 02:01:20 -07:00
|
|
|
if ((color & 0xFF00) != 0) {
|
|
|
|
int colorIndex = (color & 0xFF) - 1;
|
|
|
|
textColor = (color & ~0xFFFF) | _colorTable[_GNW_wcolor[colorIndex]];
|
2022-05-19 01:51:26 -07:00
|
|
|
} else {
|
2023-04-10 23:01:14 -07:00
|
|
|
textColor = color;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
fontDrawText(buf, str, width, window->width, textColor);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if (color & 0x01000000) {
|
2022-05-19 01:51:26 -07:00
|
|
|
// TODO: Check.
|
|
|
|
Rect rect;
|
|
|
|
rect.left = window->rect.left + x;
|
|
|
|
rect.top = window->rect.top + y;
|
2023-04-10 23:01:14 -07:00
|
|
|
rect.right = rect.left + width;
|
2022-05-19 01:51:26 -07:00
|
|
|
rect.bottom = rect.top + fontGetLineHeight();
|
|
|
|
_GNW_win_refresh(window, &rect, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D6B24
|
|
|
|
void windowDrawLine(int win, int left, int top, int right, int bottom, int color)
|
|
|
|
{
|
|
|
|
Window* window = windowGetWindow(win);
|
|
|
|
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (window == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-07-19 02:01:20 -07:00
|
|
|
if ((color & 0xFF00) != 0) {
|
|
|
|
int colorIndex = (color & 0xFF) - 1;
|
|
|
|
color = (color & ~0xFFFF) | _colorTable[_GNW_wcolor[colorIndex]];
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
bufferDrawLine(window->buffer, window->width, left, top, right, bottom, color);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D6B88
|
|
|
|
void windowDrawRect(int win, int left, int top, int right, int bottom, int color)
|
|
|
|
{
|
|
|
|
Window* window = windowGetWindow(win);
|
|
|
|
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (window == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((color & 0xFF00) != 0) {
|
2023-07-19 02:01:20 -07:00
|
|
|
int colorIndex = (color & 0xFF) - 1;
|
|
|
|
color = (color & ~0xFFFF) | _colorTable[_GNW_wcolor[colorIndex]];
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (right < left) {
|
|
|
|
int tmp = left;
|
|
|
|
left = right;
|
|
|
|
right = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bottom < top) {
|
|
|
|
int tmp = top;
|
|
|
|
top = bottom;
|
|
|
|
bottom = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
bufferDrawRect(window->buffer, window->width, left, top, right, bottom, color);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D6CC8
|
2023-04-10 23:01:14 -07:00
|
|
|
void windowFill(int win, int x, int y, int width, int height, int color)
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
Window* window = windowGetWindow(win);
|
|
|
|
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (window == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if (color == 256) {
|
2022-05-19 01:51:26 -07:00
|
|
|
if (_GNW_texture != NULL) {
|
2022-12-07 05:39:30 -08:00
|
|
|
_buf_texture(window->buffer + window->width * y + x, width, height, window->width, _GNW_texture, x + window->tx, y + window->ty);
|
2022-05-19 01:51:26 -07:00
|
|
|
} else {
|
2023-04-10 23:01:14 -07:00
|
|
|
color = _colorTable[_GNW_wcolor[0]] & 0xFF;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
2023-04-10 23:01:14 -07:00
|
|
|
} else if ((color & 0xFF00) != 0) {
|
2023-07-19 02:01:20 -07:00
|
|
|
int colorIndex = (color & 0xFF) - 1;
|
|
|
|
color = (color & ~0xFFFF) | _colorTable[_GNW_wcolor[colorIndex]];
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if (color < 256) {
|
|
|
|
bufferFill(window->buffer + window->width * y + x, width, height, window->width, color);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D6DAC
|
2022-12-12 23:37:52 -08:00
|
|
|
void windowShow(int win)
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
2022-12-12 23:37:52 -08:00
|
|
|
Window* window = windowGetWindow(win);
|
|
|
|
int index = gWindowIndexes[window->id];
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-12-12 23:37:52 -08:00
|
|
|
if ((window->flags & WINDOW_HIDDEN) != 0) {
|
2022-05-19 01:51:26 -07:00
|
|
|
window->flags &= ~WINDOW_HIDDEN;
|
2022-12-12 23:37:52 -08:00
|
|
|
if (index == gWindowsLength - 1) {
|
2022-05-19 01:51:26 -07:00
|
|
|
_GNW_win_refresh(window, &(window->rect), NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-12 23:37:52 -08:00
|
|
|
if (index < gWindowsLength - 1 && (window->flags & WINDOW_DONT_MOVE_TOP) == 0) {
|
|
|
|
while (index < gWindowsLength - 1) {
|
|
|
|
Window* nextWindow = gWindows[index + 1];
|
|
|
|
if ((window->flags & WINDOW_MOVE_ON_TOP) == 0 && (nextWindow->flags & WINDOW_MOVE_ON_TOP) != 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
gWindows[index] = nextWindow;
|
|
|
|
gWindowIndexes[nextWindow->id] = index;
|
|
|
|
index++;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2022-12-12 23:37:52 -08:00
|
|
|
gWindows[index] = window;
|
|
|
|
gWindowIndexes[window->id] = index;
|
|
|
|
_GNW_win_refresh(window, &(window->rect), NULL);
|
|
|
|
} else {
|
|
|
|
// SFALL: Fix for the window with the "DontMoveTop" flag not being
|
|
|
|
// redrawn after the show function call if it is not the topmost
|
|
|
|
// one.
|
2022-05-19 01:51:26 -07:00
|
|
|
_GNW_win_refresh(window, &(window->rect), NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D6E64
|
|
|
|
void windowHide(int win)
|
|
|
|
{
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Window* window = windowGetWindow(win);
|
|
|
|
if (window == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((window->flags & WINDOW_HIDDEN) == 0) {
|
|
|
|
window->flags |= WINDOW_HIDDEN;
|
|
|
|
_refresh_all(&(window->rect), NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D6EA0
|
|
|
|
void _win_move(int win, int x, int y)
|
|
|
|
{
|
|
|
|
Window* window = windowGetWindow(win);
|
|
|
|
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (window == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Rect rect;
|
|
|
|
rectCopy(&rect, &(window->rect));
|
|
|
|
|
|
|
|
if (x < 0) {
|
|
|
|
x = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (y < 0) {
|
|
|
|
y = 0;
|
|
|
|
}
|
|
|
|
|
2022-12-12 23:04:05 -08:00
|
|
|
if ((window->flags & WINDOW_MANAGED) != 0) {
|
2022-05-19 01:51:26 -07:00
|
|
|
x += 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (x + window->width - 1 > _scr_size.right) {
|
|
|
|
x = _scr_size.right - window->width + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (y + window->height - 1 > _scr_size.bottom) {
|
|
|
|
y = _scr_size.bottom - window->height + 1;
|
|
|
|
}
|
|
|
|
|
2022-12-12 23:04:05 -08:00
|
|
|
if ((window->flags & WINDOW_MANAGED) != 0) {
|
2022-05-19 01:51:26 -07:00
|
|
|
// TODO: Not sure what this means.
|
|
|
|
x &= ~0x03;
|
|
|
|
}
|
|
|
|
|
|
|
|
window->rect.left = x;
|
|
|
|
window->rect.top = y;
|
|
|
|
window->rect.right = window->width + x - 1;
|
|
|
|
window->rect.bottom = window->height + y - 1;
|
|
|
|
|
|
|
|
if ((window->flags & WINDOW_HIDDEN) == 0) {
|
|
|
|
_GNW_win_refresh(window, &(window->rect), NULL);
|
|
|
|
|
|
|
|
if (gWindowSystemInitialized) {
|
|
|
|
_refresh_all(&rect, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D6F5C
|
|
|
|
void windowRefresh(int win)
|
|
|
|
{
|
|
|
|
Window* window = windowGetWindow(win);
|
|
|
|
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (window == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_GNW_win_refresh(window, &(window->rect), NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D6F80
|
|
|
|
void windowRefreshRect(int win, const Rect* rect)
|
|
|
|
{
|
|
|
|
Window* window = windowGetWindow(win);
|
|
|
|
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (window == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Rect newRect;
|
|
|
|
rectCopy(&newRect, rect);
|
|
|
|
rectOffset(&newRect, window->rect.left, window->rect.top);
|
|
|
|
|
|
|
|
_GNW_win_refresh(window, &newRect, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D6FD8
|
|
|
|
void _GNW_win_refresh(Window* window, Rect* rect, unsigned char* a3)
|
|
|
|
{
|
|
|
|
RectListNode *v26, *v20, *v23, *v24;
|
|
|
|
int dest_pitch;
|
|
|
|
|
|
|
|
// TODO: Get rid of this.
|
|
|
|
dest_pitch = 0;
|
|
|
|
|
|
|
|
if ((window->flags & WINDOW_HIDDEN) != 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-12-12 23:04:05 -08:00
|
|
|
if ((window->flags & WINDOW_TRANSPARENT) && _buffering && !_doing_refresh_all) {
|
2022-05-19 01:51:26 -07:00
|
|
|
// TODO: Incomplete.
|
|
|
|
} else {
|
|
|
|
v26 = _rect_malloc();
|
|
|
|
if (v26 == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
v26->next = NULL;
|
|
|
|
|
2022-05-28 04:45:48 -07:00
|
|
|
v26->rect.left = std::max(window->rect.left, rect->left);
|
|
|
|
v26->rect.top = std::max(window->rect.top, rect->top);
|
|
|
|
v26->rect.right = std::min(window->rect.right, rect->right);
|
|
|
|
v26->rect.bottom = std::min(window->rect.bottom, rect->bottom);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
if (v26->rect.right >= v26->rect.left && v26->rect.bottom >= v26->rect.top) {
|
|
|
|
if (a3) {
|
|
|
|
dest_pitch = rect->right - rect->left + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
_win_clip(window, &v26, a3);
|
|
|
|
|
|
|
|
if (window->id) {
|
|
|
|
v20 = v26;
|
|
|
|
while (v20) {
|
|
|
|
_GNW_button_refresh(window, &(v20->rect));
|
|
|
|
|
|
|
|
if (a3) {
|
2022-12-12 23:04:05 -08:00
|
|
|
if (_buffering && (window->flags & WINDOW_TRANSPARENT)) {
|
2022-05-19 01:51:26 -07:00
|
|
|
window->blitProc(window->buffer + v20->rect.left - window->rect.left + (v20->rect.top - window->rect.top) * window->width,
|
|
|
|
v20->rect.right - v20->rect.left + 1,
|
|
|
|
v20->rect.bottom - v20->rect.top + 1,
|
|
|
|
window->width,
|
|
|
|
a3 + dest_pitch * (v20->rect.top - rect->top) + v20->rect.left - rect->left,
|
|
|
|
dest_pitch);
|
|
|
|
} else {
|
|
|
|
blitBufferToBuffer(
|
|
|
|
window->buffer + v20->rect.left - window->rect.left + (v20->rect.top - window->rect.top) * window->width,
|
|
|
|
v20->rect.right - v20->rect.left + 1,
|
|
|
|
v20->rect.bottom - v20->rect.top + 1,
|
|
|
|
window->width,
|
|
|
|
a3 + dest_pitch * (v20->rect.top - rect->top) + v20->rect.left - rect->left,
|
|
|
|
dest_pitch);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (_buffering) {
|
2022-12-12 23:04:05 -08:00
|
|
|
if (window->flags & WINDOW_TRANSPARENT) {
|
2022-05-19 01:51:26 -07:00
|
|
|
window->blitProc(
|
|
|
|
window->buffer + v20->rect.left - window->rect.left + (v20->rect.top - window->rect.top) * window->width,
|
|
|
|
v20->rect.right - v20->rect.left + 1,
|
|
|
|
v20->rect.bottom - v20->rect.top + 1,
|
|
|
|
window->width,
|
|
|
|
_screen_buffer + v20->rect.top * (_scr_size.right - _scr_size.left + 1) + v20->rect.left,
|
|
|
|
_scr_size.right - _scr_size.left + 1);
|
|
|
|
} else {
|
|
|
|
blitBufferToBuffer(
|
|
|
|
window->buffer + v20->rect.left - window->rect.left + (v20->rect.top - window->rect.top) * window->width,
|
|
|
|
v20->rect.right - v20->rect.left + 1,
|
|
|
|
v20->rect.bottom - v20->rect.top + 1,
|
|
|
|
window->width,
|
|
|
|
_screen_buffer + v20->rect.top * (_scr_size.right - _scr_size.left + 1) + v20->rect.left,
|
|
|
|
_scr_size.right - _scr_size.left + 1);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
_scr_blit(
|
|
|
|
window->buffer + v20->rect.left - window->rect.left + (v20->rect.top - window->rect.top) * window->width,
|
|
|
|
window->width,
|
|
|
|
v20->rect.bottom - v20->rect.bottom + 1,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
v20->rect.right - v20->rect.left + 1,
|
|
|
|
v20->rect.bottom - v20->rect.top + 1,
|
|
|
|
v20->rect.left,
|
|
|
|
v20->rect.top);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
v20 = v20->next;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
RectListNode* v16 = v26;
|
|
|
|
while (v16 != NULL) {
|
|
|
|
int width = v16->rect.right - v16->rect.left + 1;
|
|
|
|
int height = v16->rect.bottom - v16->rect.top + 1;
|
2022-05-21 08:22:03 -07:00
|
|
|
unsigned char* buf = (unsigned char*)internal_malloc(width * height);
|
2022-05-19 01:51:26 -07:00
|
|
|
if (buf != NULL) {
|
|
|
|
bufferFill(buf, width, height, width, _bk_color);
|
|
|
|
if (dest_pitch != 0) {
|
|
|
|
blitBufferToBuffer(
|
|
|
|
buf,
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
width,
|
|
|
|
a3 + dest_pitch * (v16->rect.top - rect->top) + v16->rect.left - rect->left,
|
|
|
|
dest_pitch);
|
|
|
|
} else {
|
|
|
|
if (_buffering) {
|
|
|
|
blitBufferToBuffer(buf,
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
width,
|
|
|
|
_screen_buffer + v16->rect.top * (_scr_size.right - _scr_size.left + 1) + v16->rect.left,
|
|
|
|
_scr_size.right - _scr_size.left + 1);
|
|
|
|
} else {
|
|
|
|
_scr_blit(buf, width, height, 0, 0, width, height, v16->rect.left, v16->rect.top);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal_free(buf);
|
|
|
|
}
|
|
|
|
v16 = v16->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
v23 = v26;
|
|
|
|
while (v23) {
|
|
|
|
v24 = v23->next;
|
|
|
|
|
|
|
|
if (_buffering && !a3) {
|
|
|
|
_scr_blit(
|
|
|
|
_screen_buffer + v23->rect.left + (_scr_size.right - _scr_size.left + 1) * v23->rect.top,
|
|
|
|
_scr_size.right - _scr_size.left + 1,
|
|
|
|
v23->rect.bottom - v23->rect.top + 1,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
v23->rect.right - v23->rect.left + 1,
|
|
|
|
v23->rect.bottom - v23->rect.top + 1,
|
|
|
|
v23->rect.left,
|
|
|
|
v23->rect.top);
|
|
|
|
}
|
|
|
|
|
|
|
|
_rect_free(v23);
|
|
|
|
|
|
|
|
v23 = v24;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!_doing_refresh_all && a3 == NULL && cursorIsHidden() == 0) {
|
|
|
|
if (_mouse_in(rect->left, rect->top, rect->right, rect->bottom)) {
|
|
|
|
mouseShowCursor();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
_rect_free(v26);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D759C
|
|
|
|
void windowRefreshAll(Rect* rect)
|
|
|
|
{
|
|
|
|
if (gWindowSystemInitialized) {
|
|
|
|
_refresh_all(rect, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D75B0
|
|
|
|
void _win_clip(Window* window, RectListNode** rectListNodePtr, unsigned char* a3)
|
|
|
|
{
|
2022-12-12 23:18:02 -08:00
|
|
|
for (int index = gWindowIndexes[window->id] + 1; index < gWindowsLength; index++) {
|
2022-05-19 01:51:26 -07:00
|
|
|
if (*rectListNodePtr == NULL) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-12-12 23:18:02 -08:00
|
|
|
Window* window = gWindows[index];
|
2022-05-19 01:51:26 -07:00
|
|
|
if (!(window->flags & WINDOW_HIDDEN)) {
|
2022-12-12 23:04:05 -08:00
|
|
|
if (!_buffering || !(window->flags & WINDOW_TRANSPARENT)) {
|
2022-05-19 01:51:26 -07:00
|
|
|
_rect_clip_list(rectListNodePtr, &(window->rect));
|
|
|
|
} else {
|
|
|
|
if (!_doing_refresh_all) {
|
|
|
|
_GNW_win_refresh(window, &(window->rect), NULL);
|
|
|
|
_rect_clip_list(rectListNodePtr, &(window->rect));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a3 == _screen_buffer || a3 == NULL) {
|
|
|
|
if (cursorIsHidden() == 0) {
|
|
|
|
Rect rect;
|
|
|
|
mouseGetRect(&rect);
|
|
|
|
_rect_clip_list(rectListNodePtr, &rect);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D765C
|
2023-07-20 00:20:05 -07:00
|
|
|
void win_drag(int win)
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
Window* window = windowGetWindow(win);
|
2023-07-20 00:20:05 -07:00
|
|
|
int dx = 0;
|
|
|
|
int dy = 0;
|
|
|
|
int mx;
|
|
|
|
int my;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (window == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-12-12 23:37:52 -08:00
|
|
|
windowShow(win);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2023-07-20 00:20:05 -07:00
|
|
|
Rect rect = window->rect;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
tickersExecute();
|
|
|
|
|
2022-07-29 06:04:05 -07:00
|
|
|
if (vcrUpdate() != 3) {
|
2022-05-19 01:51:26 -07:00
|
|
|
_mouse_info();
|
|
|
|
}
|
|
|
|
|
2023-07-20 00:20:05 -07:00
|
|
|
while ((mouseGetEvent() & MOUSE_EVENT_ANY_BUTTON_UP) == 0) {
|
|
|
|
sharedFpsLimiter.mark();
|
|
|
|
|
|
|
|
if (dx != 0 || dy != 0) {
|
|
|
|
window->rect.left += dx;
|
|
|
|
window->rect.top += dy;
|
|
|
|
window->rect.right += dx;
|
|
|
|
window->rect.bottom += dy;
|
|
|
|
_GNW_win_refresh(window, &(window->rect), NULL);
|
|
|
|
|
|
|
|
RectListNode* rectListNode = rect_clip(&rect, &(window->rect));
|
|
|
|
while (rectListNode != NULL) {
|
|
|
|
RectListNode* next = rectListNode->next;
|
|
|
|
|
|
|
|
// NOTE: Uninline.
|
|
|
|
windowRefreshAll(&(rectListNode->rect));
|
|
|
|
|
|
|
|
_rect_free(rectListNode);
|
|
|
|
rectListNode = next;
|
|
|
|
}
|
|
|
|
|
|
|
|
rect = window->rect;
|
|
|
|
}
|
|
|
|
|
|
|
|
mouseGetPosition(&mx, &my);
|
|
|
|
tickersExecute();
|
|
|
|
|
|
|
|
if (vcrUpdate() != 3) {
|
|
|
|
_mouse_info();
|
|
|
|
}
|
|
|
|
|
|
|
|
dx = mx;
|
|
|
|
dy = my;
|
|
|
|
mouseGetPosition(&mx, &my);
|
|
|
|
|
|
|
|
dx = mx - dx;
|
|
|
|
dy = my - dy;
|
|
|
|
|
|
|
|
if (dx + window->rect.left < _scr_size.left) {
|
|
|
|
dx = _scr_size.left - window->rect.left;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dx + window->rect.right > _scr_size.right) {
|
|
|
|
dx = _scr_size.right - window->rect.right;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dy + window->rect.top < _scr_size.top) {
|
|
|
|
dy = _scr_size.top - window->rect.top;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dy + window->rect.bottom > _scr_size.bottom) {
|
|
|
|
dy = _scr_size.bottom - window->rect.bottom;
|
|
|
|
}
|
|
|
|
|
|
|
|
renderPresent();
|
|
|
|
sharedFpsLimiter.throttle();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((window->flags & WINDOW_MANAGED) != 0 && (window->rect.left & 3) != 0) {
|
2022-05-19 01:51:26 -07:00
|
|
|
_win_move(window->id, window->rect.left, window->rect.top);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D77F8
|
|
|
|
void _win_get_mouse_buf(unsigned char* a1)
|
|
|
|
{
|
|
|
|
Rect rect;
|
|
|
|
mouseGetRect(&rect);
|
|
|
|
_refresh_all(&rect, a1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D7814
|
|
|
|
void _refresh_all(Rect* rect, unsigned char* a2)
|
|
|
|
{
|
|
|
|
_doing_refresh_all = 1;
|
|
|
|
|
|
|
|
for (int index = 0; index < gWindowsLength; index++) {
|
|
|
|
_GNW_win_refresh(gWindows[index], rect, a2);
|
|
|
|
}
|
|
|
|
|
|
|
|
_doing_refresh_all = 0;
|
|
|
|
|
|
|
|
if (a2 == NULL) {
|
|
|
|
if (!cursorIsHidden()) {
|
|
|
|
if (_mouse_in(rect->left, rect->top, rect->right, rect->bottom)) {
|
|
|
|
mouseShowCursor();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D7888
|
|
|
|
Window* windowGetWindow(int win)
|
|
|
|
{
|
|
|
|
if (win == -1) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2022-12-12 23:18:02 -08:00
|
|
|
int index = gWindowIndexes[win];
|
|
|
|
if (index == -1) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2022-12-12 23:18:02 -08:00
|
|
|
return gWindows[index];
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// win_get_buf
|
|
|
|
// 0x4D78B0
|
|
|
|
unsigned char* windowGetBuffer(int win)
|
|
|
|
{
|
|
|
|
Window* window = windowGetWindow(win);
|
|
|
|
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (window == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return window->buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D78CC
|
|
|
|
int windowGetAtPoint(int x, int y)
|
|
|
|
{
|
|
|
|
for (int index = gWindowsLength - 1; index >= 0; index--) {
|
|
|
|
Window* window = gWindows[index];
|
|
|
|
if (x >= window->rect.left && x <= window->rect.right
|
|
|
|
&& y >= window->rect.top && y <= window->rect.bottom) {
|
|
|
|
return window->id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D7918
|
|
|
|
int windowGetWidth(int win)
|
|
|
|
{
|
|
|
|
Window* window = windowGetWindow(win);
|
|
|
|
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (window == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return window->width;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D7934
|
|
|
|
int windowGetHeight(int win)
|
|
|
|
{
|
|
|
|
Window* window = windowGetWindow(win);
|
|
|
|
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (window == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return window->height;
|
|
|
|
}
|
|
|
|
|
|
|
|
// win_get_rect
|
|
|
|
// 0x4D7950
|
|
|
|
int windowGetRect(int win, Rect* rect)
|
|
|
|
{
|
|
|
|
Window* window = windowGetWindow(win);
|
|
|
|
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (window == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
rectCopy(rect, &(window->rect));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D797C
|
|
|
|
int _win_check_all_buttons()
|
|
|
|
{
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int v1 = -1;
|
|
|
|
for (int index = gWindowsLength - 1; index >= 1; index--) {
|
|
|
|
if (_GNW_check_buttons(gWindows[index], &v1) == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-12-12 23:04:05 -08:00
|
|
|
if ((gWindows[index]->flags & WINDOW_MODAL) != 0) {
|
2022-05-19 01:51:26 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return v1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D79DC
|
|
|
|
Button* buttonGetButton(int btn, Window** windowPtr)
|
|
|
|
{
|
|
|
|
for (int index = 0; index < gWindowsLength; index++) {
|
|
|
|
Window* window = gWindows[index];
|
|
|
|
Button* button = window->buttonListHead;
|
|
|
|
while (button != NULL) {
|
|
|
|
if (button->id == btn) {
|
|
|
|
if (windowPtr != NULL) {
|
|
|
|
*windowPtr = window;
|
|
|
|
}
|
|
|
|
|
|
|
|
return button;
|
|
|
|
}
|
|
|
|
button = button->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D7A34
|
|
|
|
int _GNW_check_menu_bars(int a1)
|
|
|
|
{
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int v1 = a1;
|
|
|
|
for (int index = gWindowsLength - 1; index >= 1; index--) {
|
|
|
|
Window* window = gWindows[index];
|
2022-07-29 06:04:05 -07:00
|
|
|
if (window->menuBar != NULL) {
|
|
|
|
for (int pulldownIndex = 0; pulldownIndex < window->menuBar->pulldownsLength; pulldownIndex++) {
|
|
|
|
if (v1 == window->menuBar->pulldowns[pulldownIndex].keyCode) {
|
|
|
|
v1 = _GNW_process_menu(window->menuBar, pulldownIndex);
|
2022-05-19 01:51:26 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-12 23:04:05 -08:00
|
|
|
if ((window->flags & WINDOW_MODAL) != 0) {
|
2022-05-19 01:51:26 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return v1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D69DC
|
|
|
|
void _win_text(int win, char** fileNameList, int fileNameListLength, int maxWidth, int x, int y, int flags)
|
|
|
|
{
|
|
|
|
Window* window = windowGetWindow(win);
|
|
|
|
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (window == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int width = window->width;
|
|
|
|
unsigned char* ptr = window->buffer + y * width + x;
|
|
|
|
int lineHeight = fontGetLineHeight();
|
2022-07-29 06:04:05 -07:00
|
|
|
|
2022-05-19 01:51:26 -07:00
|
|
|
int step = width * lineHeight;
|
|
|
|
int v1 = lineHeight / 2;
|
|
|
|
int v2 = v1 + 1;
|
|
|
|
int v3 = maxWidth - 1;
|
|
|
|
|
|
|
|
for (int index = 0; index < fileNameListLength; index++) {
|
|
|
|
char* fileName = fileNameList[index];
|
|
|
|
if (*fileName != '\0') {
|
|
|
|
windowDrawText(win, fileName, maxWidth, x, y, flags);
|
|
|
|
} else {
|
|
|
|
if (maxWidth != 0) {
|
|
|
|
bufferDrawLine(ptr, width, 0, v1, v3, v1, _colorTable[_GNW_wcolor[2]]);
|
|
|
|
bufferDrawLine(ptr, width, 0, v2, v3, v2, _colorTable[_GNW_wcolor[1]]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr += step;
|
|
|
|
y += lineHeight;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D80D8
|
|
|
|
void programWindowSetTitle(const char* title)
|
|
|
|
{
|
|
|
|
if (title == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-29 12:08:13 -07:00
|
|
|
#ifdef _WIN32
|
2022-05-19 01:51:26 -07:00
|
|
|
if (_GNW95_title_mutex == INVALID_HANDLE_VALUE) {
|
|
|
|
_GNW95_title_mutex = CreateMutexA(NULL, TRUE, title);
|
|
|
|
if (GetLastError() != ERROR_SUCCESS) {
|
|
|
|
_GNW95_already_running = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2022-05-29 12:08:13 -07:00
|
|
|
#endif
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
strncpy(gProgramWindowTitle, title, 256);
|
|
|
|
gProgramWindowTitle[256 - 1] = '\0';
|
|
|
|
|
2022-05-25 12:41:11 -07:00
|
|
|
if (gSdlWindow != nullptr) {
|
|
|
|
SDL_SetWindowTitle(gSdlWindow, gProgramWindowTitle);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// [open] implementation for palette operations backed by [XFile].
|
|
|
|
//
|
|
|
|
// 0x4D8174
|
|
|
|
int paletteOpenFileImpl(const char* path, int flags)
|
|
|
|
{
|
|
|
|
char mode[4];
|
|
|
|
memset(mode, 0, sizeof(mode));
|
|
|
|
|
|
|
|
if ((flags & 0x01) != 0) {
|
|
|
|
mode[0] = 'w';
|
|
|
|
} else if ((flags & 0x10) != 0) {
|
|
|
|
mode[0] = 'a';
|
|
|
|
} else {
|
|
|
|
mode[0] = 'r';
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((flags & 0x100) != 0) {
|
|
|
|
mode[1] = 't';
|
|
|
|
} else if ((flags & 0x200) != 0) {
|
|
|
|
mode[1] = 'b';
|
|
|
|
}
|
|
|
|
|
|
|
|
File* stream = fileOpen(path, mode);
|
|
|
|
if (stream != NULL) {
|
2022-07-05 01:00:55 -07:00
|
|
|
return ptrToInt(stream);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// [read] implementation for palette file operations backed by [XFile].
|
|
|
|
//
|
|
|
|
// 0x4D81E8
|
|
|
|
int paletteReadFileImpl(int fd, void* buf, size_t count)
|
|
|
|
{
|
2022-07-05 01:00:55 -07:00
|
|
|
return fileRead(buf, 1, count, (File*)intToPtr(fd));
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// [close] implementation for palette file operations backed by [XFile].
|
|
|
|
//
|
|
|
|
// 0x4D81E0
|
|
|
|
int paletteCloseFileImpl(int fd)
|
|
|
|
{
|
2022-07-05 01:00:55 -07:00
|
|
|
return fileClose((File*)intToPtr(fd));
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D8200
|
|
|
|
bool showMesageBox(const char* text)
|
|
|
|
{
|
2022-05-25 12:41:11 -07:00
|
|
|
SDL_Cursor* prev = SDL_GetCursor();
|
|
|
|
SDL_Cursor* cursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
|
|
|
|
SDL_SetCursor(cursor);
|
|
|
|
SDL_ShowCursor(SDL_ENABLE);
|
|
|
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, NULL, text, NULL);
|
|
|
|
SDL_ShowCursor(SDL_DISABLE);
|
|
|
|
SDL_SetCursor(prev);
|
|
|
|
SDL_FreeCursor(cursor);
|
2022-05-19 01:51:26 -07:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D8260
|
|
|
|
int buttonCreate(int win, int x, int y, int width, int height, int mouseEnterEventCode, int mouseExitEventCode, int mouseDownEventCode, int mouseUpEventCode, unsigned char* up, unsigned char* dn, unsigned char* hover, int flags)
|
|
|
|
{
|
|
|
|
Window* window = windowGetWindow(win);
|
|
|
|
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (window == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (up == NULL && (dn != NULL || hover != NULL)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
Button* button = buttonCreateInternal(win, x, y, width, height, mouseEnterEventCode, mouseExitEventCode, mouseDownEventCode, mouseUpEventCode, flags | BUTTON_FLAG_GRAPHIC, up, dn, hover);
|
2022-05-19 01:51:26 -07:00
|
|
|
if (button == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
_button_draw(button, window, button->normalImage, false, NULL, false);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
return button->id;
|
|
|
|
}
|
|
|
|
|
2022-07-29 06:04:05 -07:00
|
|
|
// 0x4D8308
|
|
|
|
int _win_register_text_button(int win, int x, int y, int mouseEnterEventCode, int mouseExitEventCode, int mouseDownEventCode, int mouseUpEventCode, const char* title, int flags)
|
|
|
|
{
|
|
|
|
Window* window = windowGetWindow(win);
|
|
|
|
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (window == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int buttonWidth = fontGetStringWidth(title) + 16;
|
|
|
|
int buttonHeight = fontGetLineHeight() + 7;
|
|
|
|
unsigned char* normal = (unsigned char*)internal_malloc(buttonWidth * buttonHeight);
|
|
|
|
if (normal == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned char* pressed = (unsigned char*)internal_malloc(buttonWidth * buttonHeight);
|
|
|
|
if (pressed == NULL) {
|
|
|
|
internal_free(normal);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
if (window->color == 256 && _GNW_texture != NULL) {
|
2022-07-29 06:04:05 -07:00
|
|
|
// TODO: Incomplete.
|
|
|
|
} else {
|
2022-12-07 05:39:30 -08:00
|
|
|
bufferFill(normal, buttonWidth, buttonHeight, buttonWidth, window->color);
|
|
|
|
bufferFill(pressed, buttonWidth, buttonHeight, buttonWidth, window->color);
|
2022-07-29 06:04:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
_lighten_buf(normal, buttonWidth, buttonHeight, buttonWidth);
|
|
|
|
|
|
|
|
fontDrawText(normal + buttonWidth * 3 + 8, title, buttonWidth, buttonWidth, _colorTable[_GNW_wcolor[3]]);
|
|
|
|
bufferDrawRectShadowed(normal,
|
|
|
|
buttonWidth,
|
|
|
|
2,
|
|
|
|
2,
|
|
|
|
buttonWidth - 3,
|
|
|
|
buttonHeight - 3,
|
|
|
|
_colorTable[_GNW_wcolor[1]],
|
|
|
|
_colorTable[_GNW_wcolor[2]]);
|
|
|
|
bufferDrawRectShadowed(normal,
|
|
|
|
buttonWidth,
|
|
|
|
1,
|
|
|
|
1,
|
|
|
|
buttonWidth - 2,
|
|
|
|
buttonHeight - 2,
|
|
|
|
_colorTable[_GNW_wcolor[1]],
|
|
|
|
_colorTable[_GNW_wcolor[2]]);
|
|
|
|
bufferDrawRect(normal, buttonWidth, 0, 0, buttonWidth - 1, buttonHeight - 1, _colorTable[0]);
|
|
|
|
|
|
|
|
fontDrawText(pressed + buttonWidth * 4 + 9, title, buttonWidth, buttonWidth, _colorTable[_GNW_wcolor[3]]);
|
|
|
|
bufferDrawRectShadowed(pressed,
|
|
|
|
buttonWidth,
|
|
|
|
2,
|
|
|
|
2,
|
|
|
|
buttonWidth - 3,
|
|
|
|
buttonHeight - 3,
|
|
|
|
_colorTable[_GNW_wcolor[2]],
|
|
|
|
_colorTable[_GNW_wcolor[1]]);
|
|
|
|
bufferDrawRectShadowed(pressed,
|
|
|
|
buttonWidth,
|
|
|
|
1,
|
|
|
|
1,
|
|
|
|
buttonWidth - 2,
|
|
|
|
buttonHeight - 2,
|
|
|
|
_colorTable[_GNW_wcolor[2]],
|
|
|
|
_colorTable[_GNW_wcolor[1]]);
|
|
|
|
bufferDrawRect(pressed, buttonWidth, 0, 0, buttonWidth - 1, buttonHeight - 1, _colorTable[0]);
|
|
|
|
|
|
|
|
Button* button = buttonCreateInternal(win,
|
|
|
|
x,
|
|
|
|
y,
|
|
|
|
buttonWidth,
|
|
|
|
buttonHeight,
|
|
|
|
mouseEnterEventCode,
|
|
|
|
mouseExitEventCode,
|
|
|
|
mouseDownEventCode,
|
|
|
|
mouseUpEventCode,
|
|
|
|
flags,
|
|
|
|
normal,
|
|
|
|
pressed,
|
|
|
|
NULL);
|
|
|
|
if (button == NULL) {
|
|
|
|
internal_free(normal);
|
|
|
|
internal_free(pressed);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
_button_draw(button, window, button->normalImage, false, NULL, false);
|
2022-07-29 06:04:05 -07:00
|
|
|
|
|
|
|
return button->id;
|
|
|
|
}
|
|
|
|
|
2022-05-19 01:51:26 -07:00
|
|
|
// 0x4D8674
|
|
|
|
int _win_register_button_disable(int btn, unsigned char* up, unsigned char* down, unsigned char* hover)
|
|
|
|
{
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Button* button = buttonGetButton(btn, NULL);
|
|
|
|
if (button == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-12-07 05:42:37 -08:00
|
|
|
button->disabledNormalImage = up;
|
|
|
|
button->disabledPressedImage = down;
|
|
|
|
button->disabledHoverImage = hover;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D86A8
|
2023-04-10 23:01:14 -07:00
|
|
|
int _win_register_button_image(int btn, unsigned char* up, unsigned char* down, unsigned char* hover, bool draw)
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (up == NULL && (down != NULL || hover != NULL)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Window* window;
|
|
|
|
Button* button = buttonGetButton(btn, &window);
|
|
|
|
if (button == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if (!(button->flags & BUTTON_FLAG_GRAPHIC)) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned char* data = button->currentImage;
|
2022-12-07 05:42:37 -08:00
|
|
|
if (data == button->normalImage) {
|
2022-05-19 01:51:26 -07:00
|
|
|
button->currentImage = up;
|
2022-12-07 05:42:37 -08:00
|
|
|
} else if (data == button->pressedImage) {
|
2022-05-19 01:51:26 -07:00
|
|
|
button->currentImage = down;
|
2022-12-07 05:42:37 -08:00
|
|
|
} else if (data == button->hoverImage) {
|
2022-05-19 01:51:26 -07:00
|
|
|
button->currentImage = hover;
|
|
|
|
}
|
|
|
|
|
2022-12-07 05:42:37 -08:00
|
|
|
button->normalImage = up;
|
|
|
|
button->pressedImage = down;
|
|
|
|
button->hoverImage = hover;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
_button_draw(button, window, button->currentImage, draw, NULL, false);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sets primitive callbacks on the button.
|
|
|
|
//
|
|
|
|
// 0x4D8758
|
|
|
|
int buttonSetMouseCallbacks(int btn, ButtonCallback* mouseEnterProc, ButtonCallback* mouseExitProc, ButtonCallback* mouseDownProc, ButtonCallback* mouseUpProc)
|
|
|
|
{
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Button* button = buttonGetButton(btn, NULL);
|
|
|
|
if (button == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
button->mouseEnterProc = mouseEnterProc;
|
|
|
|
button->mouseExitProc = mouseExitProc;
|
|
|
|
button->leftMouseDownProc = mouseDownProc;
|
|
|
|
button->leftMouseUpProc = mouseUpProc;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D8798
|
|
|
|
int buttonSetRightMouseCallbacks(int btn, int rightMouseDownEventCode, int rightMouseUpEventCode, ButtonCallback* rightMouseDownProc, ButtonCallback* rightMouseUpProc)
|
|
|
|
{
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Button* button = buttonGetButton(btn, NULL);
|
|
|
|
if (button == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
button->rightMouseDownEventCode = rightMouseDownEventCode;
|
|
|
|
button->rightMouseUpEventCode = rightMouseUpEventCode;
|
|
|
|
button->rightMouseDownProc = rightMouseDownProc;
|
|
|
|
button->rightMouseUpProc = rightMouseUpProc;
|
|
|
|
|
|
|
|
if (rightMouseDownEventCode != -1 || rightMouseUpEventCode != -1 || rightMouseDownProc != NULL || rightMouseUpProc != NULL) {
|
|
|
|
button->flags |= BUTTON_FLAG_RIGHT_MOUSE_BUTTON_CONFIGURED;
|
|
|
|
} else {
|
|
|
|
button->flags &= ~BUTTON_FLAG_RIGHT_MOUSE_BUTTON_CONFIGURED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sets button state callbacks.
|
|
|
|
// [a2] - when button is transitioning to pressed state
|
|
|
|
// [a3] - when button is returned to unpressed state
|
|
|
|
//
|
|
|
|
// The changes in the state are tied to graphical state, therefore these callbacks are not generated for
|
|
|
|
// buttons with no graphics.
|
|
|
|
//
|
|
|
|
// These callbacks can be triggered several times during tracking if mouse leaves button's rectangle without releasing mouse buttons.
|
|
|
|
//
|
|
|
|
// 0x4D87F8
|
2023-04-10 23:01:14 -07:00
|
|
|
int buttonSetCallbacks(int btn, ButtonCallback* pressSoundFunc, ButtonCallback* releaseSoundFunc)
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Button* button = buttonGetButton(btn, NULL);
|
|
|
|
if (button == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
button->pressSoundFunc = pressSoundFunc;
|
|
|
|
button->releaseSoundFunc = releaseSoundFunc;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D8828
|
|
|
|
int buttonSetMask(int btn, unsigned char* mask)
|
|
|
|
{
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Button* button = buttonGetButton(btn, NULL);
|
|
|
|
if (button == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
button->mask = mask;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D8854
|
|
|
|
Button* buttonCreateInternal(int win, int x, int y, int width, int height, int mouseEnterEventCode, int mouseExitEventCode, int mouseDownEventCode, int mouseUpEventCode, int flags, unsigned char* up, unsigned char* dn, unsigned char* hover)
|
|
|
|
{
|
|
|
|
Window* window = windowGetWindow(win);
|
|
|
|
if (window == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2022-05-21 08:22:03 -07:00
|
|
|
Button* button = (Button*)internal_malloc(sizeof(*button));
|
2022-05-19 01:51:26 -07:00
|
|
|
if (button == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((flags & BUTTON_FLAG_0x01) == 0) {
|
|
|
|
if ((flags & BUTTON_FLAG_0x02) != 0) {
|
|
|
|
flags &= ~BUTTON_FLAG_0x02;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((flags & BUTTON_FLAG_0x04) != 0) {
|
|
|
|
flags &= ~BUTTON_FLAG_0x04;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-01 08:41:37 -07:00
|
|
|
// NOTE: Uninline.
|
|
|
|
int buttonId = button_new_id();
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
button->id = buttonId;
|
|
|
|
button->flags = flags;
|
|
|
|
button->rect.left = x;
|
|
|
|
button->rect.top = y;
|
|
|
|
button->rect.right = x + width - 1;
|
|
|
|
button->rect.bottom = y + height - 1;
|
|
|
|
button->mouseEnterEventCode = mouseEnterEventCode;
|
|
|
|
button->mouseExitEventCode = mouseExitEventCode;
|
|
|
|
button->lefMouseDownEventCode = mouseDownEventCode;
|
|
|
|
button->leftMouseUpEventCode = mouseUpEventCode;
|
|
|
|
button->rightMouseDownEventCode = -1;
|
|
|
|
button->rightMouseUpEventCode = -1;
|
2022-12-07 05:42:37 -08:00
|
|
|
button->normalImage = up;
|
|
|
|
button->pressedImage = dn;
|
|
|
|
button->hoverImage = hover;
|
|
|
|
button->disabledNormalImage = NULL;
|
|
|
|
button->disabledPressedImage = NULL;
|
|
|
|
button->disabledHoverImage = NULL;
|
2022-05-19 01:51:26 -07:00
|
|
|
button->currentImage = NULL;
|
|
|
|
button->mask = NULL;
|
|
|
|
button->mouseEnterProc = NULL;
|
|
|
|
button->mouseExitProc = NULL;
|
|
|
|
button->leftMouseDownProc = NULL;
|
|
|
|
button->leftMouseUpProc = NULL;
|
|
|
|
button->rightMouseDownProc = NULL;
|
|
|
|
button->rightMouseUpProc = NULL;
|
2023-04-10 23:01:14 -07:00
|
|
|
button->pressSoundFunc = NULL;
|
|
|
|
button->releaseSoundFunc = NULL;
|
|
|
|
button->buttonGroup = NULL;
|
2022-05-19 01:51:26 -07:00
|
|
|
button->prev = NULL;
|
|
|
|
|
|
|
|
button->next = window->buttonListHead;
|
|
|
|
if (button->next != NULL) {
|
|
|
|
button->next->prev = button;
|
|
|
|
}
|
|
|
|
window->buttonListHead = button;
|
|
|
|
|
|
|
|
return button;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D89E4
|
|
|
|
bool _win_button_down(int btn)
|
|
|
|
{
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Button* button = buttonGetButton(btn, NULL);
|
|
|
|
if (button == NULL) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if ((button->flags & BUTTON_FLAG_0x01) != 0 && (button->flags & BUTTON_FLAG_CHECKED) != 0) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D8A10
|
|
|
|
int _GNW_check_buttons(Window* window, int* keyCodePtr)
|
|
|
|
{
|
|
|
|
Rect v58;
|
2022-12-07 05:39:30 -08:00
|
|
|
Button* prevHoveredButton;
|
|
|
|
Button* prevClickedButton;
|
2022-05-19 01:51:26 -07:00
|
|
|
Button* button;
|
|
|
|
|
|
|
|
if ((window->flags & WINDOW_HIDDEN) != 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
button = window->buttonListHead;
|
2022-12-07 05:39:30 -08:00
|
|
|
prevHoveredButton = window->hoveredButton;
|
|
|
|
prevClickedButton = window->clickedButton;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
if (prevHoveredButton != NULL) {
|
|
|
|
rectCopy(&v58, &(prevHoveredButton->rect));
|
2022-05-19 01:51:26 -07:00
|
|
|
rectOffset(&v58, window->rect.left, window->rect.top);
|
2022-12-07 05:39:30 -08:00
|
|
|
} else if (prevClickedButton != NULL) {
|
|
|
|
rectCopy(&v58, &(prevClickedButton->rect));
|
2022-05-19 01:51:26 -07:00
|
|
|
rectOffset(&v58, window->rect.left, window->rect.top);
|
|
|
|
}
|
|
|
|
|
|
|
|
*keyCodePtr = -1;
|
|
|
|
|
|
|
|
if (_mouse_click_in(window->rect.left, window->rect.top, window->rect.right, window->rect.bottom)) {
|
|
|
|
int mouseEvent = mouseGetEvent();
|
|
|
|
if ((window->flags & WINDOW_FLAG_0x40) || (mouseEvent & MOUSE_EVENT_LEFT_BUTTON_DOWN) == 0) {
|
|
|
|
if (mouseEvent == 0) {
|
2022-12-07 05:39:30 -08:00
|
|
|
window->clickedButton = NULL;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
} else {
|
2022-12-12 23:37:52 -08:00
|
|
|
windowShow(window->id);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
if (prevHoveredButton != NULL) {
|
|
|
|
if (!_button_under_mouse(prevHoveredButton, &v58)) {
|
|
|
|
if (!(prevHoveredButton->flags & BUTTON_FLAG_DISABLED)) {
|
|
|
|
*keyCodePtr = prevHoveredButton->mouseExitEventCode;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if ((prevHoveredButton->flags & BUTTON_FLAG_0x01) && (prevHoveredButton->flags & BUTTON_FLAG_CHECKED)) {
|
|
|
|
_button_draw(prevHoveredButton, window, prevHoveredButton->pressedImage, true, NULL, true);
|
2022-05-19 01:51:26 -07:00
|
|
|
} else {
|
2023-04-10 23:01:14 -07:00
|
|
|
_button_draw(prevHoveredButton, window, prevHoveredButton->normalImage, true, NULL, true);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
window->hoveredButton = NULL;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
_last_button_winID = window->id;
|
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
if (!(prevHoveredButton->flags & BUTTON_FLAG_DISABLED)) {
|
|
|
|
if (prevHoveredButton->mouseExitProc != NULL) {
|
|
|
|
prevHoveredButton->mouseExitProc(prevHoveredButton->id, *keyCodePtr);
|
|
|
|
if (!(prevHoveredButton->flags & BUTTON_FLAG_0x40)) {
|
2022-05-19 01:51:26 -07:00
|
|
|
*keyCodePtr = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2022-12-07 05:39:30 -08:00
|
|
|
button = prevHoveredButton;
|
|
|
|
} else if (prevClickedButton != NULL) {
|
|
|
|
if (_button_under_mouse(prevClickedButton, &v58)) {
|
|
|
|
if (!(prevClickedButton->flags & BUTTON_FLAG_DISABLED)) {
|
|
|
|
*keyCodePtr = prevClickedButton->mouseEnterEventCode;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if ((prevClickedButton->flags & BUTTON_FLAG_0x01) && (prevClickedButton->flags & BUTTON_FLAG_CHECKED)) {
|
|
|
|
_button_draw(prevClickedButton, window, prevClickedButton->pressedImage, true, NULL, true);
|
2022-05-19 01:51:26 -07:00
|
|
|
} else {
|
2023-04-10 23:01:14 -07:00
|
|
|
_button_draw(prevClickedButton, window, prevClickedButton->normalImage, true, NULL, true);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
window->hoveredButton = prevClickedButton;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
_last_button_winID = window->id;
|
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
if (!(prevClickedButton->flags & BUTTON_FLAG_DISABLED)) {
|
|
|
|
if (prevClickedButton->mouseEnterProc != NULL) {
|
|
|
|
prevClickedButton->mouseEnterProc(prevClickedButton->id, *keyCodePtr);
|
|
|
|
if (!(prevClickedButton->flags & BUTTON_FLAG_0x40)) {
|
2022-05-19 01:51:26 -07:00
|
|
|
*keyCodePtr = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int v25 = _last_button_winID;
|
|
|
|
if (_last_button_winID != -1 && _last_button_winID != window->id) {
|
|
|
|
Window* v26 = windowGetWindow(_last_button_winID);
|
|
|
|
if (v26 != NULL) {
|
|
|
|
_last_button_winID = -1;
|
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
Button* v28 = v26->hoveredButton;
|
2022-05-19 01:51:26 -07:00
|
|
|
if (v28 != NULL) {
|
|
|
|
if (!(v28->flags & BUTTON_FLAG_DISABLED)) {
|
|
|
|
*keyCodePtr = v28->mouseExitEventCode;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if ((v28->flags & BUTTON_FLAG_0x01) && (v28->flags & BUTTON_FLAG_CHECKED)) {
|
|
|
|
_button_draw(v28, v26, v28->pressedImage, true, NULL, true);
|
2022-05-19 01:51:26 -07:00
|
|
|
} else {
|
2023-04-10 23:01:14 -07:00
|
|
|
_button_draw(v28, v26, v28->normalImage, true, NULL, true);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
v26->clickedButton = NULL;
|
|
|
|
v26->hoveredButton = NULL;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
if (!(v28->flags & BUTTON_FLAG_DISABLED)) {
|
|
|
|
if (v28->mouseExitProc != NULL) {
|
|
|
|
v28->mouseExitProc(v28->id, *keyCodePtr);
|
|
|
|
if (!(v28->flags & BUTTON_FLAG_0x40)) {
|
|
|
|
*keyCodePtr = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ButtonCallback* cb = NULL;
|
|
|
|
|
|
|
|
while (button != NULL) {
|
|
|
|
if (!(button->flags & BUTTON_FLAG_DISABLED)) {
|
|
|
|
rectCopy(&v58, &(button->rect));
|
|
|
|
rectOffset(&v58, window->rect.left, window->rect.top);
|
|
|
|
if (_button_under_mouse(button, &v58)) {
|
|
|
|
if (!(button->flags & BUTTON_FLAG_DISABLED)) {
|
|
|
|
if ((mouseEvent & MOUSE_EVENT_ANY_BUTTON_DOWN) != 0) {
|
|
|
|
if ((mouseEvent & MOUSE_EVENT_RIGHT_BUTTON_DOWN) != 0 && (button->flags & BUTTON_FLAG_RIGHT_MOUSE_BUTTON_CONFIGURED) == 0) {
|
|
|
|
button = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
if (button != window->hoveredButton && button != window->clickedButton) {
|
2022-05-19 01:51:26 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
window->clickedButton = button;
|
|
|
|
window->hoveredButton = button;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
if ((button->flags & BUTTON_FLAG_0x01) != 0) {
|
|
|
|
if ((button->flags & BUTTON_FLAG_0x02) != 0) {
|
2023-04-10 23:01:14 -07:00
|
|
|
if ((button->flags & BUTTON_FLAG_CHECKED) != 0) {
|
2022-05-19 01:51:26 -07:00
|
|
|
if (!(button->flags & BUTTON_FLAG_0x04)) {
|
2023-04-10 23:01:14 -07:00
|
|
|
if (button->buttonGroup != NULL) {
|
|
|
|
button->buttonGroup->currChecked--;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((mouseEvent & MOUSE_EVENT_LEFT_BUTTON_DOWN) != 0) {
|
|
|
|
*keyCodePtr = button->leftMouseUpEventCode;
|
|
|
|
cb = button->leftMouseUpProc;
|
|
|
|
} else {
|
|
|
|
*keyCodePtr = button->rightMouseUpEventCode;
|
|
|
|
cb = button->rightMouseUpProc;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
button->flags &= ~BUTTON_FLAG_CHECKED;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (_button_check_group(button) == -1) {
|
|
|
|
button = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((mouseEvent & MOUSE_EVENT_LEFT_BUTTON_DOWN) != 0) {
|
|
|
|
*keyCodePtr = button->lefMouseDownEventCode;
|
|
|
|
cb = button->leftMouseDownProc;
|
|
|
|
} else {
|
|
|
|
*keyCodePtr = button->rightMouseDownEventCode;
|
|
|
|
cb = button->rightMouseDownProc;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
button->flags |= BUTTON_FLAG_CHECKED;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (_button_check_group(button) == -1) {
|
|
|
|
button = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((mouseEvent & MOUSE_EVENT_LEFT_BUTTON_DOWN) != 0) {
|
|
|
|
*keyCodePtr = button->lefMouseDownEventCode;
|
|
|
|
cb = button->leftMouseDownProc;
|
|
|
|
} else {
|
|
|
|
*keyCodePtr = button->rightMouseDownEventCode;
|
|
|
|
cb = button->rightMouseDownProc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
_button_draw(button, window, button->pressedImage, true, NULL, true);
|
2022-05-19 01:51:26 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
Button* v49 = window->clickedButton;
|
2022-05-19 01:51:26 -07:00
|
|
|
if (button == v49 && (mouseEvent & MOUSE_EVENT_ANY_BUTTON_UP) != 0) {
|
2022-12-07 05:39:30 -08:00
|
|
|
window->clickedButton = NULL;
|
|
|
|
window->hoveredButton = v49;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
if (v49->flags & BUTTON_FLAG_0x01) {
|
|
|
|
if (!(v49->flags & BUTTON_FLAG_0x02)) {
|
2023-04-10 23:01:14 -07:00
|
|
|
if (v49->flags & BUTTON_FLAG_CHECKED) {
|
2022-05-19 01:51:26 -07:00
|
|
|
if (!(v49->flags & BUTTON_FLAG_0x04)) {
|
2023-04-10 23:01:14 -07:00
|
|
|
if (v49->buttonGroup != NULL) {
|
|
|
|
v49->buttonGroup->currChecked--;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((mouseEvent & MOUSE_EVENT_LEFT_BUTTON_UP) != 0) {
|
|
|
|
*keyCodePtr = button->leftMouseUpEventCode;
|
|
|
|
cb = button->leftMouseUpProc;
|
|
|
|
} else {
|
|
|
|
*keyCodePtr = button->rightMouseUpEventCode;
|
|
|
|
cb = button->rightMouseUpProc;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
button->flags &= ~BUTTON_FLAG_CHECKED;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (_button_check_group(v49) == -1) {
|
|
|
|
button = NULL;
|
2023-04-10 23:01:14 -07:00
|
|
|
_button_draw(v49, window, v49->normalImage, true, NULL, true);
|
2022-05-19 01:51:26 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((mouseEvent & MOUSE_EVENT_LEFT_BUTTON_UP) != 0) {
|
|
|
|
*keyCodePtr = v49->lefMouseDownEventCode;
|
|
|
|
cb = v49->leftMouseDownProc;
|
|
|
|
} else {
|
|
|
|
*keyCodePtr = v49->rightMouseDownEventCode;
|
|
|
|
cb = v49->rightMouseDownProc;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
v49->flags |= BUTTON_FLAG_CHECKED;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2023-04-10 23:01:14 -07:00
|
|
|
if (v49->flags & BUTTON_FLAG_CHECKED) {
|
|
|
|
if (v49->buttonGroup != NULL) {
|
|
|
|
v49->buttonGroup->currChecked--;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((mouseEvent & MOUSE_EVENT_LEFT_BUTTON_UP) != 0) {
|
|
|
|
*keyCodePtr = v49->leftMouseUpEventCode;
|
|
|
|
cb = v49->leftMouseUpProc;
|
|
|
|
} else {
|
|
|
|
*keyCodePtr = v49->rightMouseUpEventCode;
|
|
|
|
cb = v49->rightMouseUpProc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-07 05:42:37 -08:00
|
|
|
if (button->hoverImage != NULL) {
|
2023-04-10 23:01:14 -07:00
|
|
|
_button_draw(button, window, button->hoverImage, true, NULL, true);
|
2022-05-19 01:51:26 -07:00
|
|
|
} else {
|
2023-04-10 23:01:14 -07:00
|
|
|
_button_draw(button, window, button->normalImage, true, NULL, true);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
if (window->hoveredButton == NULL && mouseEvent == 0) {
|
|
|
|
window->hoveredButton = button;
|
2022-05-19 01:51:26 -07:00
|
|
|
if (!(button->flags & BUTTON_FLAG_DISABLED)) {
|
|
|
|
*keyCodePtr = button->mouseEnterEventCode;
|
|
|
|
cb = button->mouseEnterProc;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
_button_draw(button, window, button->hoverImage, true, NULL, true);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
button = button->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (button != NULL) {
|
2023-07-20 01:13:01 -07:00
|
|
|
if ((button->flags & BUTTON_DRAG_HANDLE) != 0
|
2022-05-19 01:51:26 -07:00
|
|
|
&& (mouseEvent & MOUSE_EVENT_ANY_BUTTON_DOWN) != 0
|
|
|
|
&& (mouseEvent & MOUSE_EVENT_ANY_BUTTON_REPEAT) == 0) {
|
2023-07-20 00:20:05 -07:00
|
|
|
win_drag(window->id);
|
2023-04-10 23:01:14 -07:00
|
|
|
_button_draw(button, window, button->normalImage, true, NULL, true);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
2023-07-20 01:13:01 -07:00
|
|
|
} else if ((window->flags & WINDOW_DRAGGABLE_BY_BACKGROUND) != 0) {
|
2022-05-19 01:51:26 -07:00
|
|
|
v25 |= mouseEvent << 8;
|
|
|
|
if ((mouseEvent & MOUSE_EVENT_ANY_BUTTON_DOWN) != 0
|
|
|
|
&& (mouseEvent & MOUSE_EVENT_ANY_BUTTON_REPEAT) == 0) {
|
2023-07-20 00:20:05 -07:00
|
|
|
win_drag(window->id);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_last_button_winID = window->id;
|
|
|
|
|
|
|
|
if (button != NULL) {
|
|
|
|
if (cb != NULL) {
|
|
|
|
cb(button->id, *keyCodePtr);
|
|
|
|
if (!(button->flags & BUTTON_FLAG_0x40)) {
|
|
|
|
*keyCodePtr = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
if (prevHoveredButton != NULL) {
|
|
|
|
*keyCodePtr = prevHoveredButton->mouseExitEventCode;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
unsigned char* data;
|
2023-04-10 23:01:14 -07:00
|
|
|
if ((prevHoveredButton->flags & BUTTON_FLAG_0x01) && (prevHoveredButton->flags & BUTTON_FLAG_CHECKED)) {
|
2022-12-07 05:42:37 -08:00
|
|
|
data = prevHoveredButton->pressedImage;
|
2022-05-19 01:51:26 -07:00
|
|
|
} else {
|
2022-12-07 05:42:37 -08:00
|
|
|
data = prevHoveredButton->normalImage;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
_button_draw(prevHoveredButton, window, data, true, NULL, true);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
window->hoveredButton = NULL;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (*keyCodePtr != -1) {
|
|
|
|
_last_button_winID = window->id;
|
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
if ((prevHoveredButton->flags & BUTTON_FLAG_DISABLED) == 0) {
|
|
|
|
if (prevHoveredButton->mouseExitProc != NULL) {
|
|
|
|
prevHoveredButton->mouseExitProc(prevHoveredButton->id, *keyCodePtr);
|
|
|
|
if (!(prevHoveredButton->flags & BUTTON_FLAG_0x40)) {
|
2022-05-19 01:51:26 -07:00
|
|
|
*keyCodePtr = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
if (prevHoveredButton != NULL) {
|
|
|
|
if ((prevHoveredButton->flags & BUTTON_FLAG_DISABLED) == 0) {
|
|
|
|
if (prevHoveredButton->mouseExitProc != NULL) {
|
|
|
|
prevHoveredButton->mouseExitProc(prevHoveredButton->id, *keyCodePtr);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D9214
|
|
|
|
bool _button_under_mouse(Button* button, Rect* rect)
|
|
|
|
{
|
|
|
|
if (!_mouse_click_in(rect->left, rect->top, rect->right, rect->bottom)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (button->mask == NULL) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
mouseGetPosition(&x, &y);
|
|
|
|
x -= rect->left;
|
|
|
|
y -= rect->top;
|
|
|
|
|
|
|
|
int width = button->rect.right - button->rect.left + 1;
|
|
|
|
return button->mask[width * y + x] != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D927C
|
|
|
|
int buttonGetWindowId(int btn)
|
|
|
|
{
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Window* window;
|
|
|
|
if (buttonGetButton(btn, &window) == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return window->id;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D92B4
|
|
|
|
int _win_last_button_winID()
|
|
|
|
{
|
|
|
|
return _last_button_winID;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D92BC
|
|
|
|
int buttonDestroy(int btn)
|
|
|
|
{
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Window* window;
|
|
|
|
Button* button = buttonGetButton(btn, &window);
|
|
|
|
if (button == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (button->prev != NULL) {
|
|
|
|
button->prev->next = button->next;
|
|
|
|
} else {
|
|
|
|
window->buttonListHead = button->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (button->next != NULL) {
|
|
|
|
button->next->prev = button->prev;
|
|
|
|
}
|
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
windowFill(window->id, button->rect.left, button->rect.top, button->rect.right - button->rect.left + 1, button->rect.bottom - button->rect.top + 1, window->color);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
if (button == window->hoveredButton) {
|
|
|
|
window->hoveredButton = NULL;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
if (button == window->clickedButton) {
|
|
|
|
window->clickedButton = NULL;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
buttonFree(button);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D9374
|
|
|
|
void buttonFree(Button* button)
|
|
|
|
{
|
2023-04-10 23:01:14 -07:00
|
|
|
if ((button->flags & BUTTON_FLAG_GRAPHIC) == 0) {
|
2022-12-07 05:42:37 -08:00
|
|
|
if (button->normalImage != NULL) {
|
|
|
|
internal_free(button->normalImage);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2022-12-07 05:42:37 -08:00
|
|
|
if (button->pressedImage != NULL) {
|
|
|
|
internal_free(button->pressedImage);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2022-12-07 05:42:37 -08:00
|
|
|
if (button->hoverImage != NULL) {
|
|
|
|
internal_free(button->hoverImage);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2022-12-07 05:42:37 -08:00
|
|
|
if (button->disabledNormalImage != NULL) {
|
|
|
|
internal_free(button->disabledNormalImage);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2022-12-07 05:42:37 -08:00
|
|
|
if (button->disabledPressedImage != NULL) {
|
|
|
|
internal_free(button->disabledPressedImage);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2022-12-07 05:42:37 -08:00
|
|
|
if (button->disabledHoverImage != NULL) {
|
|
|
|
internal_free(button->disabledHoverImage);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
ButtonGroup* buttonGroup = button->buttonGroup;
|
|
|
|
if (buttonGroup != NULL) {
|
|
|
|
for (int index = 0; index < buttonGroup->buttonsLength; index++) {
|
|
|
|
if (button == buttonGroup->buttons[index]) {
|
|
|
|
for (; index < buttonGroup->buttonsLength - 1; index++) {
|
|
|
|
buttonGroup->buttons[index] = buttonGroup->buttons[index + 1];
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
buttonGroup->buttonsLength--;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal_free(button);
|
|
|
|
}
|
|
|
|
|
2022-09-01 08:41:37 -07:00
|
|
|
// NOTE: Inlined.
|
|
|
|
//
|
|
|
|
// 0x4D9458
|
|
|
|
static int button_new_id()
|
|
|
|
{
|
|
|
|
int btn;
|
|
|
|
|
|
|
|
btn = 1;
|
|
|
|
while (buttonGetButton(btn, NULL) != NULL) {
|
|
|
|
btn++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return btn;
|
|
|
|
}
|
|
|
|
|
2022-05-19 01:51:26 -07:00
|
|
|
// 0x4D9474
|
|
|
|
int buttonEnable(int btn)
|
|
|
|
{
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Window* window;
|
|
|
|
Button* button = buttonGetButton(btn, &window);
|
|
|
|
if (button == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((button->flags & BUTTON_FLAG_DISABLED) != 0) {
|
|
|
|
button->flags &= ~BUTTON_FLAG_DISABLED;
|
2023-04-10 23:01:14 -07:00
|
|
|
_button_draw(button, window, button->currentImage, true, NULL, false);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D94D0
|
|
|
|
int buttonDisable(int btn)
|
|
|
|
{
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Window* window;
|
|
|
|
Button* button = buttonGetButton(btn, &window);
|
|
|
|
if (button == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((button->flags & BUTTON_FLAG_DISABLED) == 0) {
|
|
|
|
button->flags |= BUTTON_FLAG_DISABLED;
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
_button_draw(button, window, button->currentImage, true, NULL, false);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2022-12-07 05:39:30 -08:00
|
|
|
if (button == window->hoveredButton) {
|
|
|
|
if (window->hoveredButton->mouseExitEventCode != -1) {
|
|
|
|
enqueueInputEvent(window->hoveredButton->mouseExitEventCode);
|
|
|
|
window->hoveredButton = NULL;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D9554
|
2023-04-10 23:01:14 -07:00
|
|
|
int _win_set_button_rest_state(int btn, bool checked, int flags)
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Window* window;
|
|
|
|
Button* button = buttonGetButton(btn, &window);
|
|
|
|
if (button == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((button->flags & BUTTON_FLAG_0x01) != 0) {
|
|
|
|
int keyCode = -1;
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if ((button->flags & BUTTON_FLAG_CHECKED) != 0) {
|
|
|
|
if (!checked) {
|
|
|
|
button->flags &= ~BUTTON_FLAG_CHECKED;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if ((flags & 0x02) == 0) {
|
|
|
|
_button_draw(button, window, button->normalImage, true, NULL, false);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if (button->buttonGroup != NULL) {
|
|
|
|
button->buttonGroup->currChecked--;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
keyCode = button->leftMouseUpEventCode;
|
|
|
|
}
|
|
|
|
} else {
|
2023-04-10 23:01:14 -07:00
|
|
|
if (checked) {
|
|
|
|
button->flags |= BUTTON_FLAG_CHECKED;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if ((flags & 0x02) == 0) {
|
|
|
|
_button_draw(button, window, button->pressedImage, true, NULL, false);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if (button->buttonGroup != NULL) {
|
|
|
|
button->buttonGroup->currChecked++;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
keyCode = button->lefMouseDownEventCode;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (keyCode != -1) {
|
2023-04-10 23:01:14 -07:00
|
|
|
if ((flags & 0x01) != 0) {
|
2022-05-19 01:51:26 -07:00
|
|
|
enqueueInputEvent(keyCode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D962C
|
2023-04-10 23:01:14 -07:00
|
|
|
int _win_group_check_buttons(int buttonCount, int* btns, int maxChecked, RadioButtonCallback* func)
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if (buttonCount >= BUTTON_GROUP_BUTTON_LIST_CAPACITY) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
for (int groupIndex = 0; groupIndex < BUTTON_GROUP_LIST_CAPACITY; groupIndex++) {
|
|
|
|
ButtonGroup* buttonGroup = &(gButtonGroups[groupIndex]);
|
|
|
|
if (buttonGroup->buttonsLength == 0) {
|
|
|
|
buttonGroup->currChecked = 0;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
for (int buttonIndex = 0; buttonIndex < buttonCount; buttonIndex++) {
|
|
|
|
Button* button = buttonGetButton(btns[buttonIndex], NULL);
|
|
|
|
if (button == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
buttonGroup->buttons[buttonIndex] = button;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
button->buttonGroup = buttonGroup;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if ((button->flags & BUTTON_FLAG_CHECKED) != 0) {
|
|
|
|
buttonGroup->currChecked++;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
buttonGroup->buttonsLength = buttonCount;
|
|
|
|
buttonGroup->maxChecked = maxChecked;
|
|
|
|
buttonGroup->func = func;
|
2022-05-19 01:51:26 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D96EC
|
|
|
|
int _win_group_radio_buttons(int count, int* btns)
|
|
|
|
{
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_win_group_check_buttons(count, btns, 1, NULL) == -1) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Button* button = buttonGetButton(btns[0], NULL);
|
2023-04-10 23:01:14 -07:00
|
|
|
ButtonGroup* buttonGroup = button->buttonGroup;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
for (int index = 0; index < buttonGroup->buttonsLength; index++) {
|
|
|
|
Button* v1 = buttonGroup->buttons[index];
|
|
|
|
v1->flags |= BUTTON_FLAG_RADIO;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D9744
|
|
|
|
int _button_check_group(Button* button)
|
|
|
|
{
|
2023-04-10 23:01:14 -07:00
|
|
|
if (button->buttonGroup == NULL) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if ((button->flags & BUTTON_FLAG_RADIO) != 0) {
|
|
|
|
if (button->buttonGroup->currChecked > 0) {
|
|
|
|
for (int index = 0; index < button->buttonGroup->buttonsLength; index++) {
|
|
|
|
Button* v1 = button->buttonGroup->buttons[index];
|
|
|
|
if ((v1->flags & BUTTON_FLAG_CHECKED) != 0) {
|
|
|
|
v1->flags &= ~BUTTON_FLAG_CHECKED;
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
Window* window;
|
|
|
|
buttonGetButton(v1->id, &window);
|
2023-04-10 23:01:14 -07:00
|
|
|
_button_draw(v1, window, v1->normalImage, true, NULL, true);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
if (v1->leftMouseUpProc != NULL) {
|
|
|
|
v1->leftMouseUpProc(v1->id, v1->leftMouseUpEventCode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if ((button->flags & BUTTON_FLAG_CHECKED) == 0) {
|
|
|
|
button->buttonGroup->currChecked++;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if (button->buttonGroup->currChecked < button->buttonGroup->maxChecked) {
|
|
|
|
if ((button->flags & BUTTON_FLAG_CHECKED) == 0) {
|
|
|
|
button->buttonGroup->currChecked++;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if (button->buttonGroup->func != NULL) {
|
|
|
|
button->buttonGroup->func(button->id);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D9808
|
2023-04-10 23:01:14 -07:00
|
|
|
void _button_draw(Button* button, Window* window, unsigned char* data, bool draw, Rect* bound, bool sound)
|
2022-05-19 01:51:26 -07:00
|
|
|
{
|
|
|
|
unsigned char* previousImage = NULL;
|
|
|
|
if (data != NULL) {
|
|
|
|
Rect v2;
|
|
|
|
rectCopy(&v2, &(button->rect));
|
|
|
|
rectOffset(&v2, window->rect.left, window->rect.top);
|
|
|
|
|
|
|
|
Rect v3;
|
2023-04-10 23:01:14 -07:00
|
|
|
if (bound != NULL) {
|
|
|
|
if (rectIntersection(&v2, bound, &v2) == -1) {
|
2022-05-19 01:51:26 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
rectCopy(&v3, &v2);
|
|
|
|
rectOffset(&v3, -window->rect.left, -window->rect.top);
|
|
|
|
} else {
|
|
|
|
rectCopy(&v3, &(button->rect));
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if (data == button->normalImage && (button->flags & BUTTON_FLAG_CHECKED)) {
|
2022-12-07 05:42:37 -08:00
|
|
|
data = button->pressedImage;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (button->flags & BUTTON_FLAG_DISABLED) {
|
2022-12-07 05:42:37 -08:00
|
|
|
if (data == button->normalImage) {
|
|
|
|
data = button->disabledNormalImage;
|
|
|
|
} else if (data == button->pressedImage) {
|
|
|
|
data = button->disabledPressedImage;
|
|
|
|
} else if (data == button->hoverImage) {
|
|
|
|
data = button->disabledHoverImage;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
} else {
|
2022-12-07 05:42:37 -08:00
|
|
|
if (data == button->disabledNormalImage) {
|
|
|
|
data = button->normalImage;
|
|
|
|
} else if (data == button->disabledPressedImage) {
|
|
|
|
data = button->pressedImage;
|
|
|
|
} else if (data == button->disabledHoverImage) {
|
|
|
|
data = button->hoverImage;
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data) {
|
2023-04-10 23:01:14 -07:00
|
|
|
if (!draw) {
|
2022-05-19 01:51:26 -07:00
|
|
|
int width = button->rect.right - button->rect.left + 1;
|
|
|
|
if ((button->flags & BUTTON_FLAG_TRANSPARENT) != 0) {
|
|
|
|
blitBufferToBufferTrans(
|
|
|
|
data + (v3.top - button->rect.top) * width + v3.left - button->rect.left,
|
|
|
|
v3.right - v3.left + 1,
|
|
|
|
v3.bottom - v3.top + 1,
|
|
|
|
width,
|
|
|
|
window->buffer + window->width * v3.top + v3.left,
|
|
|
|
window->width);
|
|
|
|
} else {
|
|
|
|
blitBufferToBuffer(
|
|
|
|
data + (v3.top - button->rect.top) * width + v3.left - button->rect.left,
|
|
|
|
v3.right - v3.left + 1,
|
|
|
|
v3.bottom - v3.top + 1,
|
|
|
|
width,
|
|
|
|
window->buffer + window->width * v3.top + v3.left,
|
|
|
|
window->width);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
previousImage = button->currentImage;
|
|
|
|
button->currentImage = data;
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if (draw) {
|
2022-05-19 01:51:26 -07:00
|
|
|
_GNW_win_refresh(window, &v2, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
if (sound) {
|
2022-05-19 01:51:26 -07:00
|
|
|
if (previousImage != data) {
|
2023-04-10 23:01:14 -07:00
|
|
|
if (data == button->pressedImage && button->pressSoundFunc != NULL) {
|
|
|
|
button->pressSoundFunc(button->id, button->lefMouseDownEventCode);
|
|
|
|
} else if (data == button->normalImage && button->releaseSoundFunc != NULL) {
|
|
|
|
button->releaseSoundFunc(button->id, button->leftMouseUpEventCode);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D9A58
|
|
|
|
void _GNW_button_refresh(Window* window, Rect* rect)
|
|
|
|
{
|
|
|
|
Button* button = window->buttonListHead;
|
|
|
|
if (button != NULL) {
|
|
|
|
while (button->next != NULL) {
|
|
|
|
button = button->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
while (button != NULL) {
|
2023-04-10 23:01:14 -07:00
|
|
|
_button_draw(button, window, button->currentImage, false, rect, false);
|
2022-05-19 01:51:26 -07:00
|
|
|
button = button->prev;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x4D9AA0
|
|
|
|
int _win_button_press_and_release(int btn)
|
|
|
|
{
|
|
|
|
if (!gWindowSystemInitialized) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Window* window;
|
|
|
|
Button* button = buttonGetButton(btn, &window);
|
|
|
|
if (button == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
_button_draw(button, window, button->pressedImage, true, NULL, true);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
if (button->leftMouseDownProc != NULL) {
|
|
|
|
button->leftMouseDownProc(btn, button->lefMouseDownEventCode);
|
|
|
|
|
|
|
|
if ((button->flags & BUTTON_FLAG_0x40) != 0) {
|
|
|
|
enqueueInputEvent(button->lefMouseDownEventCode);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (button->lefMouseDownEventCode != -1) {
|
|
|
|
enqueueInputEvent(button->lefMouseDownEventCode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-10 23:01:14 -07:00
|
|
|
_button_draw(button, window, button->normalImage, true, NULL, true);
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
if (button->leftMouseUpProc != NULL) {
|
|
|
|
button->leftMouseUpProc(btn, button->leftMouseUpEventCode);
|
|
|
|
|
|
|
|
if ((button->flags & BUTTON_FLAG_0x40) != 0) {
|
|
|
|
enqueueInputEvent(button->leftMouseUpEventCode);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (button->leftMouseUpEventCode != -1) {
|
|
|
|
enqueueInputEvent(button->leftMouseUpEventCode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2022-09-23 05:43:44 -07:00
|
|
|
|
|
|
|
} // namespace fallout
|