#include "../tdkpin_window_messages.h" #include #include Win16FarPtr g_object_windows_application; uint8_t g_object_windows_focus_event_marker; static int32_t g_window_style; static unsigned g_sequence[32]; static unsigned g_sequence_count; static Win16FarPtr g_last_procedure; static Win16FarPtr g_last_receiver; static ObjectWindowsMessage *g_last_message; static uint16_t g_scroll_position; static uint16_t g_scroll_command; static HDC16 g_paint_dc; static RECT16 g_window_rectangle; static MSG16 g_queued_messages[4]; static unsigned g_queued_count; static unsigned g_queued_index; static HWND16 g_capture_window; static unsigned g_release_calls; static unsigned g_translate_calls; static unsigned g_dispatch_calls; static unsigned g_mouse_calls; enum Sequence { SEQ_MESSAGE = 1, SEQ_SCROLL, SEQ_BEGIN_PAINT, SEQ_PAINT, SEQ_METHOD, SEQ_END_PAINT, SEQ_GET_RECT, SEQ_CAPTURE, SEQ_TRANSLATE, SEQ_DISPATCH, SEQ_MOUSE, SEQ_RELEASE, }; static void record(unsigned value) { assert(g_sequence_count < sizeof(g_sequence) / sizeof(*g_sequence)); g_sequence[g_sequence_count++] = value; } int32_t GetWindowLong16(HWND16 window, INT16 index) { assert(window == 0x1234 && index == -16); return g_window_style; } void win16_call_object_message_handler( Win16FarPtr procedure, Win16FarPtr object, ObjectWindowsMessage *message) { g_last_procedure = procedure; g_last_receiver = object; g_last_message = message; record(SEQ_MESSAGE); } void win16_call_object_scroll_method( Win16FarPtr procedure, Win16FarPtr object, uint16_t position, uint16_t command) { g_last_procedure = procedure; g_last_receiver = object; g_scroll_position = position; g_scroll_command = command; record(SEQ_SCROLL); } HDC16 BeginPaint16(HWND16 window, Win16FarPtr paint) { assert(window == 0x1234); win16_write_u16(paint, 0, g_paint_dc); record(SEQ_BEGIN_PAINT); return g_paint_dc; } BOOL16 EndPaint16(HWND16 window, Win16FarPtr paint) { assert(window == 0x1234 && win16_read_u16(paint) == g_paint_dc); record(SEQ_END_PAINT); return 1; } void win16_call_object_paint_method( Win16FarPtr procedure, Win16FarPtr object, PAINTSTRUCT16 *paint, HDC16 dc) { assert(paint->dc == g_paint_dc && dc == g_paint_dc); g_last_procedure = procedure; g_last_receiver = object; record(SEQ_PAINT); } void win16_call_object_method( Win16FarPtr procedure, Win16FarPtr object) { g_last_procedure = procedure; g_last_receiver = object; record(SEQ_METHOD); } BOOL16 GetWindowRect16(HWND16 window, Win16FarPtr rectangle) { assert(window == 0x1234); win16_write_u16(rectangle, 0, (uint16_t)g_window_rectangle.left); win16_write_u16(rectangle, 2, (uint16_t)g_window_rectangle.top); win16_write_u16(rectangle, 4, (uint16_t)g_window_rectangle.right); win16_write_u16(rectangle, 6, (uint16_t)g_window_rectangle.bottom); record(SEQ_GET_RECT); return 1; } HWND16 SetCapture16(HWND16 window) { g_capture_window = window; record(SEQ_CAPTURE); return 0xaaaa; } BOOL16 ReleaseCapture16(void) { g_release_calls++; record(SEQ_RELEASE); return 1; } BOOL16 PeekMessage16( MSG16 *message, HWND16 window, UINT16 minimum_message, UINT16 maximum_message, UINT16 remove_message) { assert(window == 0 && minimum_message == 0 && maximum_message == 0); assert(remove_message == 1); if (g_queued_index == g_queued_count) { return 0; } *message = g_queued_messages[g_queued_index++]; return 1; } BOOL16 TranslateMessage16(const MSG16 *message) { (void)message; g_translate_calls++; record(SEQ_TRANSLATE); return 1; } LRESULT16 DispatchMessage16(const MSG16 *message) { (void)message; g_dispatch_calls++; record(SEQ_DISPATCH); return 0; } void win16_call_object_u16_method( Win16FarPtr procedure, Win16FarPtr object, uint16_t argument) { assert(argument == 0x1234); g_last_procedure = procedure; g_last_receiver = object; g_mouse_calls++; record(SEQ_MOUSE); } static void write_far( Win16FarPtr base, uint16_t offset, Win16FarPtr value) { win16_write_u16(base, offset, win16_far_offset(value)); win16_write_u16( base, (uint16_t)(offset + 2), win16_far_selector(value)); } static void reset_observations(void) { g_sequence_count = 0; g_last_procedure = 0; g_last_receiver = 0; g_last_message = 0; g_queued_count = 0; g_queued_index = 0; g_release_calls = 0; g_translate_calls = 0; g_dispatch_calls = 0; g_mouse_calls = 0; } int main(void) { static uint8_t dgroup[0x1000]; uint8_t stack_anchor = 0; uintptr_t stack_base = (uintptr_t)&stack_anchor - 0x8000; win16_reset_segment_bindings(); win16_bind_segment(0x5000, dgroup, sizeof(dgroup), true); win16_set_dgroup_selector(0x5000); win16_bind_segment(0x7000, (void *)stack_base, 0x10000, true); Win16FarPtr window = win16_make_far_pointer(0x5000, 0x0200); Win16FarPtr attached = win16_make_far_pointer(0x5000, 0x0300); win16_write_u16(window, 0, 0x0400); win16_write_u16(window, 4, 0x1234); win16_write_u16(attached, 0, 0x0500); write_far(window, 0x3b, attached); Win16FarPtr default_proc = win16_make_far_pointer(0x6000, 0x1000); Win16FarPtr fallback_scroll = win16_make_far_pointer(0x6000, 0x1001); Win16FarPtr window_paint = win16_make_far_pointer(0x6000, 0x1002); Win16FarPtr horizontal = win16_make_far_pointer(0x6000, 0x2000); Win16FarPtr vertical = win16_make_far_pointer(0x6000, 0x2001); Win16FarPtr before_paint = win16_make_far_pointer(0x6000, 0x2002); Win16FarPtr after_paint = win16_make_far_pointer(0x6000, 0x2003); Win16FarPtr resize = win16_make_far_pointer(0x6000, 0x2004); Win16FarPtr mouse = win16_make_far_pointer(0x6000, 0x2005); write_far(win16_dgroup_pointer(0x0400), 0x0c, default_proc); write_far(win16_dgroup_pointer(0x0400), 0x48, fallback_scroll); write_far(win16_dgroup_pointer(0x0400), 0x4c, window_paint); write_far(win16_dgroup_pointer(0x0500), 0x20, horizontal); write_far(win16_dgroup_pointer(0x0500), 0x1c, vertical); write_far(win16_dgroup_pointer(0x0500), 0x14, before_paint); write_far(win16_dgroup_pointer(0x0500), 0x18, after_paint); write_far(win16_dgroup_pointer(0x0500), 0x0c, resize); write_far(win16_dgroup_pointer(0x0500), 0x24, mouse); ObjectWindowsMessage message = { .wparam = 7, .lparam = 0x12345678, }; reset_observations(); g_window_style = 0; object_windows_wm_hscroll_attached(window, &message); assert(g_last_procedure == fallback_scroll && g_last_receiver == window && g_last_message == &message); reset_observations(); g_window_style = 0x00100000; object_windows_wm_hscroll_attached(window, &message); assert(g_last_procedure == horizontal && g_last_receiver == attached); assert(g_scroll_position == 0x5678 && g_scroll_command == 7); reset_observations(); write_far(window, 0x3b, 0); object_windows_wm_hscroll_attached(window, &message); assert(g_last_procedure == default_proc && g_last_receiver == window); write_far(window, 0x3b, attached); reset_observations(); g_window_style = 0x00200000; object_windows_wm_vscroll_attached(window, &message); assert(g_last_procedure == vertical && g_last_receiver == attached); reset_observations(); g_paint_dc = 0x4444; object_windows_wm_paint_attached(window, &message); assert(g_sequence_count == 5); assert(g_sequence[0] == SEQ_BEGIN_PAINT); assert(g_sequence[1] == SEQ_PAINT); assert(g_sequence[2] == SEQ_PAINT); assert(g_sequence[3] == SEQ_METHOD); assert(g_sequence[4] == SEQ_END_PAINT); assert(g_last_procedure == after_paint && g_last_receiver == attached); reset_observations(); g_window_rectangle = (RECT16){10, 20, 70, 100}; message.wparam = 0; object_windows_wm_size_attached(window, &message); assert(g_sequence[0] == SEQ_METHOD); assert(g_sequence[1] == SEQ_GET_RECT); assert(g_sequence[2] == SEQ_MESSAGE); assert(win16_read_u16(win16_far_add_offset(window, 0x2d)) == 60); assert(win16_read_u16(win16_far_add_offset(window, 0x2f)) == 80); reset_observations(); message.wparam = 1; object_windows_wm_size_attached(window, &message); assert(g_sequence_count == 1 && g_sequence[0] == SEQ_MESSAGE); reset_observations(); win16_write_u8(win16_far_add_offset(attached, 0x22), 1); g_queued_messages[0].message = 0x0200; g_queued_messages[1].message = 0x0202; g_queued_count = 2; object_windows_track_mouse_until_button_up(window, &message); assert(g_capture_window == 0x1234 && g_release_calls == 1); assert(g_translate_calls == 2 && g_dispatch_calls == 2); assert(g_mouse_calls == 2); assert(g_sequence[g_sequence_count - 1] == SEQ_MESSAGE); reset_observations(); win16_set_indeterminate_u16(0x0202); object_windows_track_mouse_until_button_up(window, &message); assert(g_mouse_calls == 1 && g_release_calls == 1); reset_observations(); win16_write_u8(win16_far_add_offset(attached, 0x22), 0); object_windows_track_mouse_until_button_up(window, &message); assert(g_capture_window == 0x1234); assert(g_mouse_calls == 0 && g_release_calls == 0); assert(g_sequence_count == 1 && g_sequence[0] == SEQ_MESSAGE); return 0; }