/* ObjectWindows modal-dialog methods from Code2. */ #include "tdkpin_dialog.h" enum { OBJECT_WINDOW_HANDLE_OFFSET = 4, DIALOG_MODAL_FLAG_OFFSET = 0x25, DIALOG_CLOSE_SLOT = 0x50, DIALOG_CAN_CLOSE_SLOT = 0x3c, DIALOG_TRANSFER_SLOT = 0x44, DIALOG_MARK_CHILD_CALLBACK_OFFSET = 0x2bb1, }; 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)); } /* * 1008:2996 -- base ObjectWindows dialog constructor. The hidden VMT value * is explicit in C. A selector-zero template is an integer resource and is * retained verbatim; a real far C string is duplicated and owned by dialog. */ Win16FarPtr object_windows_dialog_construct( Win16FarPtr dialog, uint16_t vmt, Win16FarPtr template_name, Win16FarPtr parent) { BorlandObjectCallFrame frame = {dialog, vmt}; if (!borland_enter_object_constructor(&frame, 0)) { return frame.object; } frame.object = object_windows_object_construct(frame.object, 0, parent); object_windows_clear_flag_4(frame.object); Win16FarPtr stored_template = win16_far_selector(template_name) == 0 ? template_name : borland_far_strdup(template_name); write_far(frame.object, 0x1d, stored_template); write_far(frame.object, 0x21, 0); win16_write_u8(win16_far_add_offset(frame.object, 0x25), 0); return frame.object; } /* * 1008:1607 -- derived text-entry dialog. Template 7f02 is normal and 7f05 * is selected by the process flag at 066a. Four caller fields are then stored * unaligned at +26, +2a, +2e, and +32. */ Win16FarPtr object_windows_text_dialog_construct( Win16FarPtr dialog, uint16_t vmt, INT16 control_id, Win16FarPtr text_buffer, Win16FarPtr label, Win16FarPtr caption, Win16FarPtr parent) { BorlandObjectCallFrame frame = {dialog, vmt}; if (!borland_enter_object_constructor(&frame, 0)) { return frame.object; } uint16_t resource = g_dialog_alternate_template != 0 ? 0x7f05 : 0x7f02; frame.object = object_windows_dialog_construct( frame.object, 0, win16_make_far_pointer(0, resource), parent); write_far(frame.object, 0x26, caption); write_far(frame.object, 0x2a, label); write_far(frame.object, 0x2e, text_buffer); win16_write_u16(frame.object, 0x32, (uint16_t)control_id); return frame.object; } static HWND16 dialog_parent_window(Win16FarPtr dialog) { Win16FarPtr parent = win16_read_far_pointer(dialog, 6); return parent == 0 ? 0 : win16_read_u16(win16_far_add_offset(parent, 4)); } /* * 1008:2a45 -- create a modeless dialog once. AL is the Boolean result, but * AH is intentionally retained from CreateDialogParam (or incoming AX when a * preexisting status skips creation), matching MOV AL,0 / INC AX exactly. */ uint16_t object_windows_create_modeless_dialog(Win16FarPtr dialog) { uint16_t status = win16_read_u16(win16_far_add_offset(dialog, 2)); uint16_t high_byte; if (status == 0) { object_windows_clear_flag_4(dialog); object_windows_set_flag_1(dialog); win16_write_u8(win16_far_add_offset(dialog, 0x25), 0); HWND16 created = win16_call_create_dialog_param( g_win16_create_dialog_param, g_win16_instance, win16_read_far_pointer(dialog, 0x1d), dialog_parent_window(dialog), win16_read_far_pointer(dialog, 0x12), (LPARAM16)win16_read_far_pointer(dialog, 0x21)); high_byte = created & 0xff00u; win16_write_u16(dialog, 4, created); if (created == 0) { win16_write_u16(dialog, 2, 0xffff); } } else { high_byte = win16_indeterminate_u16() & 0xff00u; } return high_byte | (win16_read_u16(win16_far_add_offset(dialog, 2)) == 0 ? 1u : 0u); } /* * 1008:2ae3 -- execute a modal dialog while temporarily publishing it as the * application's active dialog. DialogBox failure -1 becomes status ffff; * the object HWND is always cleared after an attempted modal call. */ INT16 object_windows_execute_modal_dialog(Win16FarPtr dialog) { uint16_t status = win16_read_u16(win16_far_add_offset(dialog, 2)); if (status != 0) { return (INT16)status; } object_windows_clear_flag_4(dialog); object_windows_set_flag_1(dialog); win16_write_u8(win16_far_add_offset(dialog, 0x25), 1); Win16FarPtr previous_active = win16_read_far_pointer(g_object_windows_application, 0x0e); INT16 result = win16_call_dialog_box_param( g_win16_dialog_box_param, g_win16_instance, win16_read_far_pointer(dialog, 0x1d), dialog_parent_window(dialog), win16_read_far_pointer(dialog, 0x12), (LPARAM16)win16_read_far_pointer(dialog, 0x21)); write_far(g_object_windows_application, 0x0e, previous_active); if (result == -1) { win16_write_u16(dialog, 2, 0xffff); } win16_write_u16(dialog, 4, 0); return result; } /* * 1008:2cf2 -- nonmodal windows use the ordinary close helper. An active * modal dialog first asks VMT +3c; approval invokes +44(object,1) followed by * +50(object,1). The incoming message record is intentionally ignored. */ void object_windows_dialog_validate_and_close( Win16FarPtr dialog, ObjectWindowsMessage *message) { (void)message; if (win16_read_u8(win16_far_add_offset( dialog, DIALOG_MODAL_FLAG_OFFSET)) == 0) { object_windows_close_if_allowed(dialog); return; } uint16_t vmt = win16_read_u16(dialog); Win16FarPtr vmt_pointer = win16_dgroup_pointer(vmt); Win16FarPtr can_close = win16_read_far_pointer(vmt_pointer, DIALOG_CAN_CLOSE_SLOT); if (!win16_call_object_bool_method(can_close, dialog)) { return; } win16_call_object_u16_method( win16_read_far_pointer(vmt_pointer, DIALOG_TRANSFER_SLOT), dialog, 1); win16_call_object_u16_method( win16_read_far_pointer(vmt_pointer, DIALOG_CLOSE_SLOT), dialog, 1); } /* 1008:2bb1 — ForEach callback: mark a child only after HWND publication. */ void object_windows_dialog_mark_child( uint16_t ignored, Win16FarPtr child) { object_windows_set_flag_4_if_windowed(ignored, child); } /* 1008:2bd1 — end an active modal dialog after marking all child windows. */ void object_windows_end_modal_dialog( Win16FarPtr dialog, INT16 result) { if (win16_read_u8(win16_far_add_offset( dialog, DIALOG_MODAL_FLAG_OFFSET)) == 0) { return; } object_windows_for_each_child( dialog, win16_relocated_code_pointer( 2, DIALOG_MARK_CHILD_CALLBACK_OFFSET)); HWND16 window = win16_read_u16(win16_far_add_offset( dialog, OBJECT_WINDOW_HANDLE_OFFSET)); (void)EndDialog16(window, result); } /* * 1008:2d3a — modal dialogs use VMT +0x50(object,2); nonmodal windows use the * ordinary close-if-allowed helper. The incoming event is ignored. */ void object_windows_dialog_close( Win16FarPtr dialog, ObjectWindowsMessage *message) { (void)message; if (win16_read_u8(win16_far_add_offset( dialog, DIALOG_MODAL_FLAG_OFFSET)) == 0) { object_windows_close_if_allowed(dialog); return; } uint16_t vmt = win16_read_u16(dialog); Win16FarPtr procedure = win16_read_far_pointer(win16_dgroup_pointer(vmt), DIALOG_CLOSE_SLOT); win16_call_object_u16_method(procedure, dialog, 2); } /* * 1008:2a0e — derived dialog destructor. The binary tests only the selector * word of the unaligned string pointer at +0x1d/+0x1f before disposing it. */ void object_windows_dialog_destruct(Win16FarPtr dialog, uint16_t vmt) { Win16FarPtr string = win16_read_far_pointer(dialog, 0x1d); if (win16_far_selector(string) != 0) { borland_far_strdispose(string); } object_windows_object_destruct(dialog, 0); BorlandObjectCallFrame frame = {dialog, vmt}; borland_finish_object_destructor(&frame, 0); } /* 1008:168e — fill the dialog's far text buffer and always return AL=1. */ bool object_windows_dialog_read_text(Win16FarPtr dialog) { HWND16 window = win16_read_u16(win16_far_add_offset(dialog, 4)); Win16FarPtr buffer = win16_read_far_pointer(dialog, 0x2e); INT16 control_id = (INT16)win16_read_u16( win16_far_add_offset(dialog, 0x32)); (void)GetDlgItemTextFar16(window, control_id, buffer, 0x65); return true; } /* * 1008:16be -- finish ObjectWindows preparation, publish the caption and two * control texts, then limit control +0x32 to length-1 with EM_LIMITTEXT 0415h. * Every USER return value is deliberately ignored. */ void object_windows_dialog_setup_text_fields(Win16FarPtr dialog) { object_windows_prepare_window(dialog); HWND16 window = win16_read_u16(win16_far_add_offset(dialog, 4)); (void)SetWindowTextFar16( window, win16_read_far_pointer(dialog, 0x26)); (void)SetDlgItemText16( window, 100, win16_read_far_pointer(dialog, 0x2a)); (void)SetDlgItemText16( window, 101, win16_read_far_pointer(dialog, 0x2e)); uint16_t capacity = win16_read_u16(win16_far_add_offset(dialog, 0x32)); (void)SendDlgItemMessage16( window, 101, 0x0415, (uint16_t)(capacity - 1), 0); }