/*
 * Copyright (c) 2024. The RigelA open source project team and
 * its contributors reserve all rights.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software distributed under the
 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and limitations under the License.
 * Modified by igaisin 2025
 */

pub(crate) mod callbacks;
pub(crate) mod calls;
pub(crate) mod packages;

use crate::{call_proc, utils::SafeModuleHandle};
use crate::{
    jab,
    jab::jab_lib::{
        callbacks::{
            AccessBridgeCaretUpdateFp, AccessBridgeFocusGainedFp, AccessBridgeFocusLostFp,
            AccessBridgeJavaShutdownFp, AccessBridgeMenuCanceledFp, AccessBridgeMenuDeselectedFp,
            AccessBridgeMenuSelectedFp, AccessBridgeMouseClickedFp, AccessBridgeMouseEnteredFp,
            AccessBridgeMouseExitedFp, AccessBridgeMousePressedFp, AccessBridgeMouseReleasedFp,
            AccessBridgePopupMenuCanceledFp, AccessBridgePopupMenuWillBecomeInvisibleFp,
            AccessBridgePopupMenuWillBecomeVisibleFp, AccessBridgePropertyActiveDescendentChangeFp,
            AccessBridgePropertyCaretChangeFp, AccessBridgePropertyChangeFp,
            AccessBridgePropertyChildChangeFp, AccessBridgePropertyDescriptionChangeFp,
            AccessBridgePropertyNameChangeFp, AccessBridgePropertySelectionChangeFp,
            AccessBridgePropertyStateChangeFp, AccessBridgePropertyTableModelChangeFp,
            AccessBridgePropertyTextChangeFp, AccessBridgePropertyValueChangeFp,
            AccessBridgePropertyVisibleDataChangeFp,
        },
        packages::{
            AccessBridgeVersionInfo, AccessibleActions, AccessibleActionsToDo, AccessibleContext,
            AccessibleContextInfo, AccessibleHyperlink, AccessibleHypertext,
            AccessibleHypertextInfo, AccessibleIcons, AccessibleKeyBindings,
            AccessibleRelationSetInfo, AccessibleSelection, AccessibleTable,
            AccessibleTableCellInfo, AccessibleTableInfo, AccessibleText,
            AccessibleTextAttributesInfo, AccessibleTextInfo, AccessibleTextItemsInfo,
            AccessibleTextRectInfo, AccessibleTextSelectionInfo, AccessibleValue, BOOL, JInt,
            JObject, JObject64, JavaObject, VisibleChildrenInfo,
        },
    },
};
use std::{
    env::var,
    path::{Path, PathBuf},
    ffi::CString,
};
// use win_wrap::common::{FARPROC, HWND, Result, free_library, get_proc_address, load_library};
use windows::{
    Win32::Foundation::{FreeLibrary, HWND, FARPROC, HMODULE, S_FALSE},
    Win32::System::LibraryLoader::{LoadLibraryW, GetProcAddress},
    core::{Error as WinError, HSTRING, PCSTR},
};

/**
Извлекает адрес экспортированной функции (также известной как процедура) или переменной из указанной динамически подключаемой библиотеки (DLL).
`h_module` - Дескриптор модуля DLL, содержащего функцию или переменную. Этот дескриптор возвращается функциями LoadLibrary, LoadLibraryEx, LoadPackagedLibrary или GetModuleHandle.
            Функция GetProcAddress не извлекает адреса из модулей, загруженных с флагом LOAD_LIBRARY_AS_DATAFILE. Подробнее см. в документации LoadLibraryEx.
`proc_name` - Имя функции или переменной, либо порядковое значение функции. Если этот параметр является порядковым значением, оно должно находиться в младшем слове (low-order word);
            старшее слово (high-order word) должно быть равно нулю.
*/
pub fn get_proc_address(h_module: HMODULE, proc_name: &str) -> FARPROC {
    let name = CString::new(proc_name).unwrap();
    unsafe { GetProcAddress(h_module, PCSTR::from_raw(name.as_ptr().cast())) }
}

#[allow(unused)]
#[derive(Debug)]
pub(crate) struct JabLib {
    h_module: SafeModuleHandle,
}

#[allow(dead_code)]
impl JabLib {
    //noinspection RsUnresolvedPath
    //noinspection SpellCheckingInspection
    pub(crate) fn new(path: Option<PathBuf>) -> windows::core::Result<Self> {
        #[cfg(target_arch = "x86_64")]
        const DLL_NAME: &str = "windowsaccessbridge-64.dll";
        #[cfg(target_arch = "x86")]
        const DLL_NAME: &str = "windowsaccessbridge-32.dll";
        let lib = match path {
            None => match var("JAVA_HOME") {
                Ok(s) => Path::new(&s).join("bin").join(DLL_NAME),
                Err(e) => {
                    return Err(WinError::new(
                        S_FALSE,
                        &format!("Не удается найти библиотеку jab. ({})", e),
                    ));
                }
            },
            Some(p) => p.to_path_buf(),
        };
        let h_module = match unsafe { LoadLibraryW(&HSTRING::from(lib.to_str().unwrap())) } {
            Ok(h) => SafeModuleHandle::new(h),
            Err(e) => return Err(e),
        };
        let res = jab!(*h_module, windows_run);
        if res.is_none() {
            return Err(WinError::new(
                S_FALSE,
                "Не удается загрузить библиотеку jab.",
            ));
        }
        Ok(Self { h_module })
    }

    /**
    Проверяет, реализует ли данное окно Java Accessibility API.
    */
    pub(crate) fn is_java_window(&self, h_wnd: HWND) -> bool {
        jab!(*self.h_module, is_java_window, h_wnd).unwrap_or(0) != 0
    }

    /**
    Получает AccessibleContext и vmID для данного окна. Многие функции Java Access Bridge требуют значения AccessibleContext и vmID.
    `target` Целевое окно.
    */
    pub(crate) fn get_accessible_context_from_hwnd(
        &self,
        target: HWND,
    ) -> Option<(i32, AccessibleContext)> {
        let (mut context, mut vm_id) = unsafe { std::mem::zeroed() };
        if jab!(
            *self.h_module,
            get_accessible_context_from_hwnd,
            target,
            &mut vm_id,
            &mut context
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some((vm_id, context))
    }

    /**
    Возвращает HWND из AccessibleContext верхнего уровня окна.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    */
    pub(crate) fn get_hwnd_from_accessible_context(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
    ) -> HWND {
        jab!(*self.h_module, get_hwnd__from_accessible_context, vm_id, ac)
            .unwrap_or(HWND::default())
    }

    /**
    Освобождает память, используемую объектом Java, где object - это объект, возвращенный Java Access Bridge. Java Access Bridge автоматически поддерживает ссылки на все объекты Java, которые он возвращает вам в JVM, чтобы они не были собраны мусором. Чтобы предотвратить утечки памяти, вызывайте их после завершения работы с объектами Java, возвращенными Java Access Bridge.
    `object` Объект Java.
    */
    pub(crate) fn release_java_object(&self, vm_id: i32, object: JavaObject) {
        jab!(*self.h_module, release_java_object, vm_id, object);
    }

    /**
    Получает информацию о версии экземпляра Java Access Bridge, используемого приложением. Вы можете использовать эту информацию, чтобы определить доступные функции вашей версии Java Access Bridge. Примечание: чтобы определить версию JVM, вам нужно передать действительный vm_id; в противном случае возвращается только версия файла WindowsAccessBridge.DLL, к которому подключено приложение.
    `vm_id` Идентификатор виртуальной машины.
    */
    pub(crate) fn get_version_info(&self, vm_id: i32) -> Option<AccessBridgeVersionInfo> {
        let mut info = unsafe { std::mem::zeroed() };
        if jab!(*self.h_module, get_version_info, vm_id, &mut info).unwrap_or(0) == 0 {
            return None;
        }
        Some(info)
    }

    /**
    Запрашивает объект AccessibleContext окна или объекта под указателем мыши.
    `parent` Родительский объект.
    `x` X координата.
    `y` Y координата.
    */
    pub(crate) fn get_accessible_context_at(
        &self,
        vm_id: i32,
        parent: AccessibleContext,
        x: JInt,
        y: JInt,
    ) -> Option<AccessibleContext> {
        let mut ac = unsafe { std::mem::zeroed() };
        if jab!(
            *self.h_module,
            get_accessible_context_at,
            vm_id,
            parent,
            x,
            y,
            &mut ac
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(ac)
    }

    //noinspection StructuralWrap
    /**
    Запрашивает объект AccessibleContext окна или объекта с фокусом.
    `window` Дескриптор окна для запроса.
    */
    pub(crate) fn get_accessible_context_with_focus(
        &self,
        window: HWND,
    ) -> Option<(i32, AccessibleContext)> {
        let (mut vm_id, mut ac) = unsafe { std::mem::zeroed() };
        if jab!(
            *self.h_module,
            get_accessible_context_with_focus,
            window,
            &mut vm_id,
            &mut ac
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some((vm_id, ac))
    }

    /**
    Запрашивает объект AccessibleContextInfo из объекта AccessibleContext.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    */
    pub(crate) fn get_accessible_context_info(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
    ) -> Option<AccessibleContextInfo> {
        let mut info = unsafe { std::mem::zeroed() };
        if jab!(
            *self.h_module,
            get_accessible_context_info,
            vm_id,
            ac,
            &mut info
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(info)
    }

    /**
    Возвращает объект, представляющий n-й дочерний объект данного объекта AccessibleContext, где n указан значением index.
    `ac` Контекст доступности.
    `vm_id` Идентификатор виртуальной машины.
    `index` Индекс дочернего объекта.
    */
    pub(crate) fn get_accessible_child_from_context(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
        index: JInt,
    ) -> Option<AccessibleContext> {
        jab!(
            *self.h_module,
            get_accessible_child_from_context,
            vm_id,
            ac,
            index
        )
    }

    /**
    Возвращает объект, представляющий родительский объект данного объекта AccessibleContext.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    */
    pub(crate) fn get_accessible_parent_from_context(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
    ) -> Option<AccessibleContext> {
        jab!(
            *self.h_module,
            get_accessible_parent_from_context,
            vm_id,
            ac
        )
    }

    /**
    Возвращает, ссылаются ли два объекта на один и тот же объект.
    `vm_id` Идентификатор виртуальной машины.
    `obj1` Объект 1.
    `obj2` Объект 2.
    */
    pub(crate) fn is_same_object(&self, vm_id: i32, obj1: JObject64, obj2: JObject64) -> bool {
        jab!(*self.h_module, is_same_object, vm_id, obj1, obj2).unwrap_or(0) != 0
    }

    /**
    Возвращает объект AccessibleContext с указанной ролью, который является предком данного объекта. Роль является одной из строк ролей, определенных в структуре данных Java Access Bridge API. Если объект предка с указанной ролью не существует, возвращается (AccessibleContext)0.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    `role` Строка роли.
    */
    pub(crate) fn get_parent_with_role(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
        role: &str,
    ) -> Option<AccessibleContext> {
        jab!(
            *self.h_module,
            get_parent_with_role,
            vm_id,
            ac,
            HSTRING::from(role).as_ptr()
        )
    }

    /**
    Возвращает объект AccessibleContext с указанной ролью, который является предком данного объекта. Если объект с указанной ролью не существует, возвращается объект верхнего уровня Java окна. В случае ошибки возвращается (AccessibleContext)0.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    `role` Строка роли.
    */
    pub(crate) fn get_parent_with_role_else_root(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
        role: &str,
    ) -> Option<AccessibleContext> {
        jab!(
            *self.h_module,
            get_parent_with_role_else_root,
            vm_id,
            ac,
            HSTRING::from(role).as_ptr()
        )
    }

    /**
    Возвращает объект AccessibleContext верхнего уровня Java окна. Это то же самое, что и AccessibleContext, полученный из get_accessible_context_from_hwnd для этого окна. В случае ошибки возвращается (AccessibleContext)0.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    */
    pub(crate) fn get_top_level_object(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
    ) -> Option<AccessibleContext> {
        jab!(*self.h_module, get_top_level_object, vm_id, ac)
    }

    //noinspection StructuralWrap
    /**
    Возвращает глубину объекта в иерархии объектов. Глубина объекта на вершине иерархии объектов равна 0. В случае ошибки возвращается -1.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    */
    pub(crate) fn get_object_depth(&self, vm_id: i32, ac: AccessibleContext) -> i32 {
        jab!(*self.h_module, get_object_depth, vm_id, ac).unwrap_or(-1)
    }

    /**
    Возвращает объект AccessibleContext текущего ActiveDescendent объекта. Этот метод предполагает, что ActiveDescendent - это компонент, который в настоящее время выбран в контейнерном объекте. В случае ошибки или отсутствия выбора возвращается (AccessibleContext)0.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    */
    pub(crate) fn get_active_descendent(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
    ) -> Option<AccessibleContext> {
        jab!(*self.h_module, get_active_descendent, vm_id, ac)
    }

    /**
    Запросить фокус для компонента. Возвращает true, если успешно.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    */
    pub(crate) fn request_focus(&self, vm_id: i32, ac: AccessibleContext) -> bool {
        jab!(*self.h_module, request_focus, vm_id, ac).unwrap_or(0) != 0
    }

    //noinspection StructuralWrap
    /**
    Возвращает количество видимых дочерних компонентов. В случае ошибки возвращается -1.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    */
    pub(crate) fn get_visible_children_count(&self, vm_id: i32, ac: AccessibleContext) -> i32 {
        jab!(*self.h_module, get_visible_children_count, vm_id, ac).unwrap_or(-1)
    }

    /**
    Получает видимых дочерних компонентов для AccessibleContext.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    `start_index` Начальный индекс.
    */
    pub(crate) fn get_visible_children(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
        start_index: i32,
    ) -> Option<VisibleChildrenInfo> {
        let mut info = unsafe { std::mem::zeroed() };
        if jab!(
            *self.h_module,
            get_visible_children,
            vm_id,
            ac,
            start_index,
            &mut info
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(info)
    }

    /**
    Получает количество ожидающих событий.
    */
    pub(crate) fn get_events_waiting(&self) -> i32 {
        jab!(*self.h_module, get_events_waiting).unwrap_or(0)
    }

    /**
    Возвращает список действий, которые может выполнить компонент.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    */
    pub(crate) fn get_accessible_actions(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
    ) -> Option<AccessibleActions> {
        let mut actions = unsafe { std::mem::zeroed() };
        if jab!(
            *self.h_module,
            get_accessible_actions,
            vm_id,
            ac,
            &mut actions
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(actions)
    }

    /**
    Получает местоположение каретки текста.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    `index` Индекс.
    */
    pub(crate) fn get_caret_location(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
        index: JInt,
    ) -> Option<AccessibleTextRectInfo> {
        let mut info = unsafe { std::mem::zeroed() };
        if jab!(
            *self.h_module,
            get_caret_location,
            vm_id,
            ac,
            &mut info,
            index
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(info)
    }

    /**
    Установить позицию каретки в тексте. Возвращает true, если успешно.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    `position` Позиция каретки.
    */
    pub(crate) fn set_caret_position(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
        position: i32,
    ) -> bool {
        jab!(*self.h_module, set_caret_position, vm_id, ac, position).unwrap_or(0) != 0
    }

    /**
    Получает атрибуты текста между двумя индексами. Список атрибутов включает текст в начальном индексе и текст в конечном индексе.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    `start_index` Начальный индекс.
    `end_index` Конечный индекс.
    */
    pub(crate) fn get_text_attributes_in_range(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
        start_index: i32,
        end_index: i32,
    ) -> Option<(AccessibleTextAttributesInfo, i16)> {
        let (mut info, mut len) = unsafe { std::mem::zeroed() };
        if jab!(
            *self.h_module,
            get_text_attributes_in_range,
            vm_id,
            ac,
            start_index,
            end_index,
            &mut info,
            &mut len
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some((info, len))
    }

    /**
    Возвращает информацию о наборе отношений объекта.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    */
    pub(crate) fn get_accessible_relation_set(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
    ) -> Option<AccessibleRelationSetInfo> {
        let mut info = unsafe { std::mem::zeroed() };
        if jab!(
            *self.h_module,
            get_accessible_relation_set,
            vm_id,
            ac,
            &mut info
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(info)
    }

    /**
    Возвращает список привязок клавиш, связанных с компонентом.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    */
    pub(crate) fn get_accessible_key_bindings(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
    ) -> Option<AccessibleKeyBindings> {
        let mut info = unsafe { std::mem::zeroed() };
        if jab!(
            *self.h_module,
            get_accessible_key_bindings,
            vm_id,
            ac,
            &mut info
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(info)
    }

    /**
    Возвращает список значков, связанных с компонентом.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    */
    pub(crate) fn get_accessible_icons(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
    ) -> Option<AccessibleIcons> {
        let mut info = unsafe { std::mem::zeroed() };
        if jab!(*self.h_module, get_accessible_icons, vm_id, ac, &mut info).unwrap_or(0) == 0 {
            return None;
        }
        Some(info)
    }

    /**
    Возвращает заголовок строки таблицы для указанной таблицы в виде таблицы.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    */
    pub(crate) fn get_accessible_table_row_header(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
    ) -> Option<AccessibleTableInfo> {
        let mut info = unsafe { std::mem::zeroed() };
        if jab!(
            *self.h_module,
            get_accessible_table_row_header,
            vm_id,
            ac,
            &mut info
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(info)
    }

    /**
    Возвращает заголовок столбца таблицы для указанной таблицы в виде таблицы.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    */
    pub(crate) fn get_accessible_table_column_header(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
    ) -> Option<AccessibleTableInfo> {
        let mut info = unsafe { std::mem::zeroed() };
        if jab!(
            *self.h_module,
            get_accessible_table_column_header,
            vm_id,
            ac,
            &mut info
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(info)
    }

    /**
    Возвращает описание указанного столбца в указанной таблице. Описание столбца начинается с нуля.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    `column` Индекс столбца.
    */
    pub(crate) fn get_accessible_table_column_description(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
        column: JInt,
    ) -> Option<AccessibleContext> {
        jab!(
            *self.h_module,
            get_accessible_table_column_description,
            vm_id,
            ac,
            column
        )
    }

    /**
    Возвращает описание указанной строки в указанной таблице. Описание строки начинается с нуля.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    `row` Индекс строки.
    */
    pub(crate) fn get_accessible_table_row_description(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
        row: JInt,
    ) -> Option<AccessibleContext> {
        jab!(
            *self.h_module,
            get_accessible_table_row_description,
            vm_id,
            ac,
            row
        )
    }

    /**
    Выбирает текст между двумя индексами. Выбор включает текст в начальном индексе и текст в конечном индексе. Возвращает, успешно ли выполнено.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    `start_index` Начальный индекс.
    `end_index` Конечный индекс.
    */
    pub(crate) fn select_text_range(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
        start_index: JInt,
        end_index: JInt,
    ) -> bool {
        jab!(
            *self.h_module,
            select_text_range,
            vm_id,
            ac,
            start_index,
            end_index
        )
        .unwrap_or(0)
            != 0
    }

    /**
    Получает информацию о таблице, такую как заголовок, сводка, количество строк и столбцов, и AccessibleTable.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    */
    pub(crate) fn get_accessible_table_info(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
    ) -> Option<AccessibleTableInfo> {
        let mut info = unsafe { std::mem::zeroed() };
        if jab!(
            *self.h_module,
            get_accessible_table_info,
            vm_id,
            ac,
            &mut info
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(info)
    }

    /**
    Получает виртуальное имя компонента на основе алгоритма JAWS. Возвращает, успешно ли выполнено. Bug ID 4916682-реализация политики виртуального имени JAWS
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    `len` Длина имени.
    */
    pub(crate) fn get_virtual_accessible_name(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
        len: i32,
    ) -> Option<Vec<u16>> {
        let mut name = Vec::new();
        for _ in 0..len {
            name.push(0);
        }
        if jab!(
            *self.h_module,
            get_virtual_accessible_name,
            vm_id,
            ac,
            name.as_mut_ptr(),
            len
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(name)
    }

    /**
    Возвращает информацию о гипертексте, связанную с компонентом.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    */
    pub(crate) fn get_accessible_hypertext(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
    ) -> Option<AccessibleHypertextInfo> {
        let mut info = unsafe { std::mem::zeroed() };
        if jab!(
            *self.h_module,
            get_accessible_hypertext,
            vm_id,
            ac,
            &mut info
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(info)
    }

    /**
    Перебирает гиперссылки в компоненте. Возвращает информацию о гипертексте компонента, начиная с индекса гиперссылки start_index. Для каждого вызова этого метода возвращаемый объект AccessibleHypertextInfo не превышает MAX_HYPERLINKS. В случае ошибки возвращается None.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    `start_index` Начальный индекс.
    */
    pub(crate) fn get_accessible_hypertext_ext(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
        start_index: JInt,
    ) -> Option<AccessibleHypertextInfo> {
        let mut info = unsafe { std::mem::zeroed() };
        if jab!(
            *self.h_module,
            get_accessible_hypertext_ext,
            vm_id,
            ac,
            start_index,
            &mut info
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(info)
    }

    /**
    Запрашивает выполнение списка доступных действий компонента. Если все действия выполнены, возвращает true. Если первое запрошенное действие не удалось, возвращает false, в этом случае "failure" содержит индекс неудачного действия.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    `actions_to_do` Список действий для выполнения.
    */
    pub(crate) fn do_accessible_actions(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
        actions_to_do: *const AccessibleActionsToDo,
    ) -> (bool, JInt) {
        let mut failure = unsafe { std::mem::zeroed() };
        (
            jab!(
                *self.h_module,
                do_accessible_actions,
                vm_id,
                ac,
                actions_to_do,
                &mut failure
            )
            .unwrap_or(0)
                != 0,
            failure,
        )
    }

    /**
    Устанавливает содержимое редактируемого текста. AccessibleContext должен реализовывать AccessibleEditableText и быть редактируемым. Максимальная длина текста, которую можно установить, составляет MAX_STRING_SIZE-1. Возвращает, успешно ли выполнено.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    `text` Текстовое содержимое.
    */
    pub(crate) fn set_text_contents(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
        text: *const u16,
    ) -> bool {
        jab!(*self.h_module, set_text_contents, vm_id, ac, text).unwrap_or(0) != 0
    }

    /**
    Установить обработчик для обновления каретки.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_caret_update_fp(&self, cb: AccessBridgeCaretUpdateFp) {
        jab!(*self.h_module, set_caret_update_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для получения фокуса.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_focus_gained_fp(&self, cb: AccessBridgeFocusGainedFp) {
        jab!(*self.h_module, set_focus_gained_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для потери фокуса.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_focus_lost_fp(&self, cb: AccessBridgeFocusLostFp) {
        jab!(*self.h_module, set_focus_lost_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для завершения работы JVM.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_java_shutdown_fp(&self, cb: AccessBridgeJavaShutdownFp) {
        jab!(*self.h_module, set_java_shutdown_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для отмены меню.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_menu_canceled_fp(&self, cb: AccessBridgeMenuCanceledFp) {
        jab!(*self.h_module, set_menu_canceled_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для отмены выбора меню.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_menu_deselected_fp(&self, cb: AccessBridgeMenuDeselectedFp) {
        jab!(*self.h_module, set_menu_deselected_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для выбора меню.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_menu_selected_fp(&self, cb: AccessBridgeMenuSelectedFp) {
        jab!(*self.h_module, set_menu_selected_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для щелчка мыши.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_mouse_clicked_fp(&self, cb: AccessBridgeMouseClickedFp) {
        jab!(*self.h_module, set_mouse_clicked_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для входа мыши.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_mouse_entered_fp(&self, cb: AccessBridgeMouseEnteredFp) {
        jab!(*self.h_module, set_mouse_entered_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для выхода мыши.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_mouse_exited_fp(&self, cb: AccessBridgeMouseExitedFp) {
        jab!(*self.h_module, set_mouse_exited_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для нажатия мыши.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_mouse_pressed_fp(&self, cb: AccessBridgeMousePressedFp) {
        jab!(*self.h_module, set_mouse_pressed_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для отпускания мыши.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_mouse_released_fp(&self, cb: AccessBridgeMouseReleasedFp) {
        jab!(*self.h_module, set_mouse_released_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для отмены всплывающего меню.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_popup_menu_canceled_fp(&self, cb: AccessBridgePopupMenuCanceledFp) {
        jab!(*self.h_module, set_popup_menu_canceled_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для скрытия всплывающего меню.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_popup_menu_will_become_invisible_fp(
        &self,
        cb: AccessBridgePopupMenuWillBecomeInvisibleFp,
    ) {
        jab!(*self.h_module, set_popup_menu_will_become_invisible_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для отображения всплывающего меню.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_popup_menu_will_become_visible_fp(
        &self,
        cb: AccessBridgePopupMenuWillBecomeVisibleFp,
    ) {
        jab!(*self.h_module, set_popup_menu_will_become_visible_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для изменения активного потомка свойства.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_property_active_descendent_change_fp(
        &self,
        cb: AccessBridgePropertyActiveDescendentChangeFp,
    ) {
        jab!(*self.h_module, set_property_active_descendent_change_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для изменения каретки свойства.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_property_caret_change_fp(&self, cb: AccessBridgePropertyCaretChangeFp) {
        jab!(*self.h_module, set_property_caret_change_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для изменения свойства.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_property_change_fp(&self, cb: AccessBridgePropertyChangeFp) {
        jab!(*self.h_module, set_property_change_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для изменения дочернего свойства.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_property_child_change_fp(&self, cb: AccessBridgePropertyChildChangeFp) {
        jab!(*self.h_module, set_property_child_change_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для изменения описания свойства.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_property_description_change_fp(
        &self,
        cb: AccessBridgePropertyDescriptionChangeFp,
    ) {
        jab!(*self.h_module, set_property_description_change_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для изменения имени свойства.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_property_name_change_fp(&self, cb: AccessBridgePropertyNameChangeFp) {
        jab!(*self.h_module, set_property_name_change_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для изменения выбора свойства.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_property_selection_change_fp(
        &self,
        cb: AccessBridgePropertySelectionChangeFp,
    ) {
        jab!(*self.h_module, set_property_selection_change_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для изменения состояния свойства.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_property_state_change_fp(&self, cb: AccessBridgePropertyStateChangeFp) {
        jab!(*self.h_module, set_property_state_change_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для изменения модели таблицы свойства.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_property_table_model_change_fp(
        &self,
        cb: AccessBridgePropertyTableModelChangeFp,
    ) {
        jab!(*self.h_module, set_property_table_model_change_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для изменения текста свойства.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_property_text_change_fp(&self, cb: AccessBridgePropertyTextChangeFp) {
        jab!(*self.h_module, set_property_text_change_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для изменения значения свойства.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_property_value_change_fp(&self, cb: AccessBridgePropertyValueChangeFp) {
        jab!(*self.h_module, set_property_value_change_fp, cb).unwrap_or(())
    }

    /**
    Устанавливает обработчик для изменения видимых данных свойства.
    `cb` Функция, принимающая событие.
    */
    pub(crate) fn set_property_visible_data_change_fp(
        &self,
        cb: AccessBridgePropertyVisibleDataChangeFp,
    ) {
        jab!(*self.h_module, set_property_visible_data_change_fp, cb).unwrap_or(())
    }

    /**
    Запрашивает активацию гиперссылки.
    `vm_id` Идентификатор виртуальной машины.
    `ac` Контекст доступности.
    `link` Объект гиперссылки.
    */
    pub(crate) fn activate_accessible_hyperlink(
        &self,
        vm_id: i32,
        ac: AccessibleContext,
        link: AccessibleHyperlink,
    ) -> bool {
        jab!(
            *self.h_module,
            activate_accessible_hyperlink,
            vm_id,
            ac,
            link
        )
        .unwrap_or(0)
            != 0
    }

    /**
    Добавляет элемент в выбор. Если флаг AccessibleSelection в структуре данных AccessibleContextInfo установлен в TRUE, то в AccessibleContext содержится информация о AccessibleSelection. Поддержка AccessibleSelection - это первое место, где можно манипулировать пользовательским интерфейсом, добавляя и удаляя элементы из выбора (а не запрашивая). Некоторые функции используют индексы в координатах дочерних элементов, а другие - в координатах выбора. Например, добавление в выбор и удаление из него осуществляется путем передачи индекса дочернего элемента (например, добавление четвертого дочернего элемента в выбор). С другой стороны, перечисление выбранных дочерних объектов выполняется в координатах выбора (например, получение AccessibleContext первого выбранного объекта).
    `vm_id` Идентификатор виртуальной машины.
    `as` Контекст доступности.
    `index` Индекс.
    */
    pub(crate) fn add_accessible_selection_from_context(
        &self,
        vm_id: i32,
        r#as: AccessibleSelection,
        index: i32,
    ) {
        jab!(
            *self.h_module,
            add_accessible_selection_from_context,
            vm_id,
            r#as,
            index
        )
        .unwrap_or(())
    }

    /**
    Удаляет элемент из выбора. Если флаг AccessibleSelection в структуре данных AccessibleContextInfo установлен в TRUE, то в AccessibleContext содержится информация о AccessibleSelection. Поддержка AccessibleSelection - это первое место, где можно манипулировать пользовательским интерфейсом, добавляя и удаляя элементы из выбора (а не запрашивая). Некоторые функции используют индексы в координатах дочерних элементов, а другие - в координатах выбора. Например, добавление в выбор и удаление из него осуществляется путем передачи индекса дочернего элемента (например, добавление четвертого дочернего элемента в выбор). С другой стороны, перечисление выбранных дочерних объектов выполняется в координатах выбора (например, получение AccessibleContext первого выбранного объекта).
    `vm_id` Идентификатор виртуальной машины.
    `as` Контекст доступности.
    `index` Индекс.
    */
    pub(crate) fn remove_accessible_selection_from_context(
        &self,
        vm_id: i32,
        r#as: AccessibleSelection,
        index: i32,
    ) {
        jab!(
            *self.h_module,
            remove_accessible_selection_from_context,
            vm_id,
            r#as,
            index
        )
        .unwrap_or(())
    }

    /**
    Очищает выбор. Если флаг AccessibleSelection в структуре данных AccessibleContextInfo установлен в TRUE, то в AccessibleContext содержится информация о AccessibleSelection. Поддержка AccessibleSelection - это первое место, где можно манипулировать пользовательским интерфейсом, добавляя и удаляя элементы из выбора (а не запрашивая). Некоторые функции используют индексы в координатах дочерних элементов, а другие - в координатах выбора. Например, добавление в выбор и удаление из него осуществляется путем передачи индекса дочернего элемента (например, добавление четвертого дочернего элемента в выбор). С другой стороны, перечисление выбранных дочерних объектов выполняется в координатах выбора (например, получение AccessibleContext первого выбранного объекта).
    `vm_id` Идентификатор виртуальной машины.
    `as` Контекст доступности.
    */
    pub(crate) fn clear_accessible_selection_from_context(
        &self,
        vm_id: i32,
        r#as: AccessibleSelection,
    ) {
        jab!(
            *self.h_module,
            clear_accessible_selection_from_context,
            vm_id,
            r#as
        )
        .unwrap_or(())
    }

    /**
    Выбирает все. Если флаг AccessibleSelection в структуре данных AccessibleContextInfo установлен в TRUE, то в AccessibleContext содержится информация о AccessibleSelection. Поддержка AccessibleSelection - это первое место, где можно манипулировать пользовательским интерфейсом, добавляя и удаляя элементы из выбора (а не запрашивая). Некоторые функции используют индексы в координатах дочерних элементов, а другие - в координатах выбора. Например, добавление в выбор и удаление из него осуществляется путем передачи индекса дочернего элемента (например, добавление четвертого дочернего элемента в выбор). С другой стороны, перечисление выбранных дочерних объектов выполняется в координатах выбора (например, получение AccessibleContext первого выбранного объекта).
    `vm_id` Идентификатор виртуальной машины.
    `as` Контекст доступности.
    */
    pub(crate) fn select_all_accessible_selection_from_context(
        &self,
        vm_id: i32,
        r#as: AccessibleSelection,
    ) {
        jab!(
            *self.h_module,
            select_all_accessible_selection_from_context,
            vm_id,
            r#as
        )
        .unwrap_or(())
    }

    /**
    Возвращает n-ю гиперссылку в документе. Соответствует AccessibleHypertext.getLink. В случае ошибки возвращается None.
    `vm_id` Идентификатор виртуальной машины.
    `ah` Контекст доступности гипертекста.
    `index` Индекс.
    */
    pub(crate) fn get_accessible_hyperlink(
        &self,
        vm_id: i32,
        ah: AccessibleContext,
        index: JInt,
    ) -> Option<AccessibleHypertextInfo> {
        let mut info = unsafe { std::mem::zeroed() };
        if jab!(
            *self.h_module,
            get_accessible_hyperlink,
            vm_id,
            ah,
            index,
            &mut info
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(info)
    }

    /**
    Возвращает количество гиперссылок в компоненте. Соответствует AccessibleHypertext.getLinkCount. В случае ошибки возвращается -1.
    `vm_id` Идентификатор виртуальной машины.
    `ah` Контекст доступности гипертекста.
    */
    pub(crate) fn get_accessible_hyperlink_count(
        &self,
        vm_id: i32,
        ah: AccessibleHypertext,
    ) -> JInt {
        jab!(*self.h_module, get_accessible_hyperlink_count, vm_id, ah).unwrap_or(-1)
    }

    /**
    Возвращает индекс в массиве гиперссылок, связанный с индексом символа в документе. Соответствует AccessibleHypertext.getLinkIndex. В случае ошибки возвращается -1.
    `vm_id` Идентификатор виртуальной машины.
    `ah` Контекст доступности гипертекста.
    `index` Индекс.
    */
    pub(crate) fn get_accessible_hypertext_link_index(
        &self,
        vm_id: i32,
        ah: AccessibleHypertext,
        index: JInt,
    ) -> JInt {
        jab!(
            *self.h_module,
            get_accessible_hypertext_link_index,
            vm_id,
            ah,
            index
        )
        .unwrap_or(-1)
    }

    /**
    Получает количество объектов в выборе.
    `vm_id` Идентификатор виртуальной машины.
    `as` Контекст доступности выбора.
    */
    pub(crate) fn get_accessible_selection_count_from_context(
        &self,
        vm_id: i32,
        r#as: AccessibleSelection,
    ) -> i32 {
        jab!(
            *self.h_module,
            get_accessible_selection_count_from_context,
            vm_id,
            r#as
        )
        .unwrap_or(-1)
    }

    /**
    Получает объект в выборе.
    `vm_id` Идентификатор виртуальной машины.
    `as` Контекст доступности выбора.
    `index` Индекс.
    */
    pub(crate) fn get_accessible_selection_from_context(
        &self,
        vm_id: i32,
        r#as: AccessibleSelection,
        index: i32,
    ) -> Option<JObject> {
        jab!(
            *self.h_module,
            get_accessible_selection_from_context,
            vm_id,
            r#as,
            index
        )
    }

    /**
    Определяет, выбран ли объект.
    `vm_id` Идентификатор виртуальной машины.
    `as` Контекст доступности выбора.
    `index` Индекс дочернего объекта.
    */
    pub(crate) fn is_accessible_child_selected_from_context(
        &self,
        vm_id: i32,
        r#as: AccessibleSelection,
        index: i32,
    ) -> bool {
        jab!(
            *self.h_module,
            is_accessible_child_selected_from_context,
            vm_id,
            r#as,
            index
        )
        .unwrap_or(0)
            != 0
    }

    /**
    Определяет, выбрана ли строка таблицы. Возвращает true, если указанный ряд, начиная с нуля, выбран.
    `vm_id` Идентификатор виртуальной машины.
    `at` Контекст доступности таблицы.
    `row` Индекс строки.
    */
    pub(crate) fn is_accessible_table_row_selected(
        &self,
        vm_id: i32,
        at: AccessibleTable,
        row: JInt,
    ) -> bool {
        jab!(
            *self.h_module,
            is_accessible_table_row_selected,
            vm_id,
            at,
            row
        )
        .unwrap_or(0)
            != 0
    }

    /**
    Определяет, выбран ли столбец таблицы. Возвращает true, если указанный столбец, начиная с нуля, выбран.
    `vm_id` Идентификатор виртуальной машины.
    `at` Контекст доступности таблицы.
    `column` Индекс столбца.
    */
    pub(crate) fn is_accessible_table_column_selected(
        &self,
        vm_id: i32,
        at: AccessibleTable,
        column: JInt,
    ) -> bool {
        jab!(
            *self.h_module,
            is_accessible_table_column_selected,
            vm_id,
            at,
            column
        )
        .unwrap_or(0)
            != 0
    }

    /**
    Возвращает информацию о ячейке таблицы для указанной строки и столбца. Строка и столбец начинаются с нуля.
    `vm_id` Идентификатор виртуальной машины.
    `at` Контекст доступности таблицы.
    `row` Индекс строки.
    `column` Индекс столбца.
    */
    pub(crate) fn get_accessible_table_cell_info(
        &self,
        vm_id: i32,
        at: AccessibleTable,
        row: JInt,
        column: JInt,
    ) -> Option<AccessibleTableCellInfo> {
        let mut info = unsafe { std::mem::zeroed() };
        if jab!(
            *self.h_module,
            get_accessible_table_cell_info,
            vm_id,
            at,
            row,
            column,
            &mut info
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(info)
    }

    /**
    Возвращает номер столбца для ячейки в указанном индексе ячейки. Эти значения начинаются с нуля.
    `vm_id` Идентификатор виртуальной машины.
    `at` Контекст доступности таблицы.
    `index` Индекс.
    */
    pub(crate) fn get_accessible_table_column(
        &self,
        vm_id: i32,
        at: AccessibleTable,
        index: JInt,
    ) -> JInt {
        jab!(
            *self.h_module,
            get_accessible_table_column,
            vm_id,
            at,
            index
        )
        .unwrap_or(0)
    }

    /**
    Возвращает номер строки для ячейки в указанном индексе ячейки. Эти значения начинаются с нуля.
    `vm_id` Идентификатор виртуальной машины.
    `at` Контекст доступности таблицы.
    `index` Индекс.
    */
    pub(crate) fn get_accessible_table_row(
        &self,
        vm_id: i32,
        at: AccessibleTable,
        index: JInt,
    ) -> JInt {
        jab!(*self.h_module, get_accessible_table_row, vm_id, at, index).unwrap_or(0)
    }

    /**
    Возвращает количество выбранных столбцов в таблице.
    `vm_id` Идентификатор виртуальной машины.
    `at` Контекст доступности таблицы.
    */
    pub(crate) fn get_accessible_table_column_selection_count(
        &self,
        vm_id: i32,
        at: AccessibleTable,
    ) -> JInt {
        jab!(
            *self.h_module,
            get_accessible_table_column_selection_count,
            vm_id,
            at
        )
        .unwrap_or(0)
    }

    /**
    Возвращает количество выбранных строк в таблице.
    `vm_id` Идентификатор виртуальной машины.
    `at` Контекст доступности таблицы.
    */
    pub(crate) fn get_accessible_table_row_selection_count(
        &self,
        vm_id: i32,
        at: AccessibleTable,
    ) -> JInt {
        jab!(
            *self.h_module,
            get_accessible_table_row_selection_count,
            vm_id,
            at
        )
        .unwrap_or(0)
    }

    /**
    Возвращает индекс для указанной строки и столбца в таблице. Эти значения начинаются с нуля.
    `vm_id` Идентификатор виртуальной машины.
    `at` Контекст доступности таблицы.
    `row` Индекс строки.
    `column` Индекс столбца.
    */
    pub(crate) fn get_accessible_table_index(
        &self,
        vm_id: i32,
        at: AccessibleTable,
        row: JInt,
        column: JInt,
    ) -> JInt {
        jab!(
            *self.h_module,
            get_accessible_table_index,
            vm_id,
            at,
            row,
            column
        )
        .unwrap_or(0)
    }

    /**
    Возвращает массив индексов выбранных столбцов, начиная с нуля.
    `vm_id` Идентификатор виртуальной машины.
    `at` Контекст доступности таблицы.
    `count` Длина массива.
    */
    pub(crate) fn get_accessible_table_column_selections(
        &self,
        vm_id: i32,
        at: AccessibleTable,
        count: JInt,
    ) -> Option<Vec<JInt>> {
        let mut arr = Vec::new();
        for _ in 0..count {
            arr.push(0);
        }
        if jab!(
            *self.h_module,
            get_accessible_table_column_selections,
            vm_id,
            at,
            count,
            arr.as_mut_ptr()
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        return Some(arr);
    }

    /**
    Возвращает массив индексов выбранных строк, начиная с нуля.
    `vm_id` Идентификатор виртуальной машины.
    `at` Контекст доступности таблицы.
    `count` Длина массива.
    */
    pub(crate) fn get_accessible_table_row_selections(
        &self,
        vm_id: i32,
        at: AccessibleTable,
        count: JInt,
    ) -> Option<Vec<JInt>> {
        let mut arr = Vec::new();
        for _ in 0..count {
            arr.push(0);
        }
        if jab!(
            *self.h_module,
            get_accessible_table_row_selections,
            vm_id,
            at,
            count,
            arr.as_mut_ptr()
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        return Some(arr);
    }

    /**
    Получает информацию о выборе текста. Если флаг AccessibleText в структуре данных AccessibleContextInfo установлен в TRUE, то в AccessibleContext содержится информация о AccessibleText. Файл AccessBridgePackages.h определяет значения структур, используемых в этих функциях. Java Access Bridge API описывает их обратные вызовы.
    `vm_id` Идентификатор виртуальной машины.
    `at` Контекст доступности текста.
    */
    pub(crate) fn get_accessible_text_selection_info(
        &self,
        vm_id: i32,
        at: AccessibleText,
    ) -> Option<AccessibleTextSelectionInfo> {
        let mut info = unsafe { std::mem::zeroed() };
        if jab!(
            *self.h_module,
            get_accessible_text_selection_info,
            vm_id,
            at,
            &mut info
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(info)
    }

    /**
    Получает информацию о тексте. Если флаг AccessibleText в структуре данных AccessibleContextInfo установлен в TRUE, то в AccessibleContext содержится информация о AccessibleText. Файл AccessBridgePackages.h определяет значения структур, используемых в этих функциях. Java Access Bridge API описывает их обратные вызовы.
    `vm_id` Идентификатор виртуальной машины.
    `at` Контекст доступности текста.
    `x` X координата.
    `y` Y координата.
    */
    pub(crate) fn get_accessible_text_info(
        &self,
        vm_id: i32,
        at: AccessibleText,
        x: JInt,
        y: JInt,
    ) -> Option<AccessibleTextInfo> {
        let mut info = unsafe { std::mem::zeroed() };
        if jab!(
            *self.h_module,
            get_accessible_text_info,
            vm_id,
            at,
            &mut info,
            x,
            y
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(info)
    }

    /**
    Получает атрибуты текста. Если флаг AccessibleText в структуре данных AccessibleContextInfo установлен в TRUE, то в AccessibleContext содержится информация о AccessibleText. Файл AccessBridgePackages.h определяет значения структур, используемых в этих функциях. Java Access Bridge API описывает их обратные вызовы.
    `vm_id` Идентификатор виртуальной машины.
    `at` Контекст доступности текста.
    `index` Индекс.
    */
    pub(crate) fn get_accessible_text_attributes(
        &self,
        vm_id: i32,
        at: AccessibleText,
        index: JInt,
    ) -> (*const u8, AccessibleTextAttributesInfo) {
        let mut info = unsafe { std::mem::zeroed() };
        let char = jab!(
            *self.h_module,
            get_accessible_text_attributes,
            vm_id,
            at,
            index,
            &mut info
        )
        .unwrap_or(std::ptr::null());
        (char, info)
    }

    /**
    Получает элементы текста. Если флаг AccessibleText в структуре данных AccessibleContextInfo установлен в TRUE, то в AccessibleContext содержится информация о AccessibleText. Файл AccessBridgePackages.h определяет значения структур, используемых в этих функциях. Java Access Bridge API описывает их обратные вызовы.
    `vm_id` Идентификатор виртуальной машины.
    `at` Контекст доступности текста.
    `index` Индекс.
    */
    pub(crate) fn get_accessible_text_items(
        &self,
        vm_id: i32,
        at: AccessibleText,
        index: JInt,
    ) -> Option<AccessibleTextItemsInfo> {
        let mut info = unsafe { std::mem::zeroed() };
        if jab!(
            *self.h_module,
            get_accessible_text_items,
            vm_id,
            at,
            &mut info,
            index
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(info)
    }

    /**
    Получает границы строки текста. Если флаг AccessibleText в структуре данных AccessibleContextInfo установлен в TRUE, то в AccessibleContext содержится информация о AccessibleText. Файл AccessBridgePackages.h определяет значения структур, используемых в этих функциях. Java Access Bridge API описывает их обратные вызовы.
    `vm_id` Идентификатор виртуальной машины.
    `at` Контекст доступности текста.
    `index` Индекс.
    */
    pub(crate) fn get_accessible_text_line_bounds(
        &self,
        vm_id: i32,
        at: AccessibleText,
        index: JInt,
    ) -> Option<(JInt, JInt)> {
        let (mut start, mut end) = unsafe { std::mem::zeroed() };
        if jab!(
            *self.h_module,
            get_accessible_text_line_bounds,
            vm_id,
            at,
            index,
            &mut start,
            &mut end
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some((start, end))
    }

    /**
    Получает диапазон текста. Если флаг AccessibleText в структуре данных AccessibleContextInfo установлен в TRUE, то в AccessibleContext содержится информация о AccessibleText. Файл AccessBridgePackages.h определяет значения структур, используемых в этих функциях. Java Access Bridge API описывает их обратные вызовы.
    `vm_id` Идентификатор виртуальной машины.
    `at` Контекст доступности текста.
    `start_index` Начальный индекс.
    `end_index` Конечный индекс.
    `len` Длина.
    */
    pub(crate) fn get_accessible_text_range(
        &self,
        vm_id: i32,
        at: AccessibleText,
        start_index: JInt,
        end_index: JInt,
        len: i16,
    ) -> Option<Vec<u16>> {
        let mut text = Vec::new();
        for _ in 0..len {
            text.push(0);
        }
        if jab!(
            *self.h_module,
            get_accessible_text_range,
            vm_id,
            at,
            start_index,
            end_index,
            text.as_mut_ptr(),
            len
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(text)
    }

    /**
    Получает прямоугольную область текста. Если флаг AccessibleText в структуре данных AccessibleContextInfo установлен в TRUE, то в AccessibleContext содержится информация о AccessibleText. Файл AccessBridgePackages.h определяет значения структур, используемых в этих функциях. Java Access Bridge API описывает их обратные вызовы.
    `vm_id` Идентификатор виртуальной машины.
    `at` Контекст доступности текста.
    `index` Индекс.
    */
    pub(crate) fn get_accessible_text_rect(
        &self,
        vm_id: i32,
        at: AccessibleText,
        index: JInt,
    ) -> Option<AccessibleTextRectInfo> {
        let mut info = unsafe { std::mem::zeroed() };
        if jab!(
            *self.h_module,
            get_accessible_text_rect,
            vm_id,
            at,
            &mut info,
            index
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(info)
    }

    /**
    Получает текущее значение. Если флаг AccessibleValue в структуре данных AccessibleContextInfo установлен в TRUE, то в объекте AccessibleContext содержится информация о AccessibleValue. Возвращаемое значение является строкой (char*value), так как невозможно заранее определить, является ли значение целым числом, числом с плавающей запятой или другим объектом, являющимся подклассом java.lang.Number в языке Java.
    `vm_id` Идентификатор виртуальной машины.
    `av` Контекст доступности значения.
    `len` Длина текста.
    */
    pub(crate) fn get_current_accessible_value_from_context(
        &self,
        vm_id: i32,
        av: AccessibleValue,
        len: i16,
    ) -> Option<Vec<u16>> {
        let mut value = Vec::new();
        for _ in 0..len {
            value.push(0);
        }
        if jab!(
            *self.h_module,
            get_current_accessible_value_from_context,
            vm_id,
            av,
            value.as_mut_ptr(),
            len
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(value)
    }

    /**
    Получает максимальное значение. Если флаг AccessibleValue в структуре данных AccessibleContextInfo установлен в TRUE, то в объекте AccessibleContext содержится информация о AccessibleValue. Возвращаемое значение является строкой (char*value), так как невозможно заранее определить, является ли значение целым числом, числом с плавающей запятой или другим объектом, являющимся подклассом java.lang.Number в языке Java.
    `vm_id` Идентификатор виртуальной машины.
    `av` Контекст доступности значения.
    `len` Длина текста.
    */
    pub(crate) fn get_maximum_accessible_value_from_context(
        &self,
        vm_id: i32,
        av: AccessibleValue,
        len: i16,
    ) -> Option<Vec<u16>> {
        let mut value = Vec::new();
        for _ in 0..len {
            value.push(0);
        }
        if jab!(
            *self.h_module,
            get_maximum_accessible_value_from_context,
            vm_id,
            av,
            value.as_mut_ptr(),
            len
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(value)
    }

    /**
    Получает минимальное значение. Если флаг AccessibleValue в структуре данных AccessibleContextInfo установлен в TRUE, то в объекте AccessibleContext содержится информация о AccessibleValue. Возвращаемое значение является строкой (char*value), так как невозможно заранее определить, является ли значение целым числом, числом с плавающей запятой или другим объектом, являющимся подклассом java.lang.Number в языке Java.
    `vm_id` Идентификатор виртуальной машины.
    `av` Контекст доступности значения.
    `len` Длина текста.
    */
    pub(crate) fn get_minimum_accessible_value_from_context(
        &self,
        vm_id: i32,
        av: AccessibleValue,
        len: i16,
    ) -> Option<Vec<u16>> {
        let mut value = Vec::new();
        for _ in 0..len {
            value.push(0);
        }
        if jab!(
            *self.h_module,
            get_minimum_accessible_value_from_context,
            vm_id,
            av,
            value.as_mut_ptr(),
            len
        )
        .unwrap_or(0)
            == 0
        {
            return None;
        }
        Some(value)
    }
}

impl Drop for JabLib {
    fn drop(&mut self) {
        if self.h_module.is_invalid() {
            return;
        }
        unsafe { FreeLibrary(*self.h_module).unwrap_or(()) };
    }
}
