{
 * Keyman is copyright (C) SIL International. MIT License.
 *
 * Interface for Keyman Core, matches keyboardprocessor.h
}
unit Keyman.System.KeymanCore;

interface

{$WARN SYMBOL_PLATFORM OFF}
{$ALIGN 8}

type
  uint8_t = Byte;
  uint16_t = Word;
  uint32_t = Cardinal;
  uintptr_t = NativeUInt;
  char16_t = Char;

  km_kbp_virtual_key = uint16_t;

  km_kbp_usv = uint32_t;  // UTF-32
  km_kbp_cp = WideChar;
  pkm_kbp_cp = ^km_kbp_cp;

  km_kbp_context = record end;
  pkm_kbp_context = ^km_kbp_context;

  km_kbp_keyboard = record end;
  pkm_kbp_keyboard = ^km_kbp_keyboard;

  km_kbp_state = record end;
  pkm_kbp_state = ^km_kbp_state;

  km_kbp_options = record end;
  pkm_kbp_options = ^km_kbp_options;

  km_kbp_path_name = PWideChar; // on Windows
  pkm_kbp_path_name = ^km_kbp_path_name;

type
  km_kbp_status = (
    KM_KBP_STATUS_OK = 0,
    KM_KBP_STATUS_NO_MEM = 1,
    KM_KBP_STATUS_IO_ERROR = 2,
    KM_KBP_STATUS_INVALID_ARGUMENT = 3,
    KM_KBP_STATUS_KEY_ERROR = 4,
    KM_KBP_STATUS_INSUFFICENT_BUFFER = 5,
    KM_KBP_STATUS_INVALID_UTF = 6,
    KM_KBP_STATUS_INVALID_KEYBOARD = 7
  );

type
  km_kbp_context_type = (
    KM_KBP_CT_END = 0,
    KM_KBP_CT_CHAR,
    KM_KBP_CT_MARKER
  );

  km_kbp_context_item = record
    _type: km_kbp_context_type;
{$IFDEF WIN64}
    _reserved: array[0..6] of uint8_t;
{$ELSE}
    _reserved: array[0..2] of uint8_t;
{$ENDIF}
  case integer of
    1: (character: km_kbp_usv);
    2: (marker: uint32_t);
  end;

  pkm_kbp_context_item = ^km_kbp_context_item;

const
  KM_KBP_CONTEXT_ITEM_END: km_kbp_context_item = (
    _type: KM_KBP_CT_END;
    _reserved: (0,0,0);
    character: 0
  );

const
  kmnkbp0 = 'kmnkbp0-0.dll';

function km_kbp_context_items_from_utf16(
  const text: pkm_kbp_cp;
  var out_ptr: pkm_kbp_context_item
): km_kbp_status; cdecl; external kmnkbp0 delayed;

function km_kbp_context_items_from_utf8(
  const text: PAnsiChar;
  var out_ptr: pkm_kbp_context_item
): km_kbp_status; cdecl; external kmnkbp0 delayed;

function km_kbp_context_items_to_utf16(
  const item: pkm_kbp_context_item;
  buf: pkm_kbp_cp;
  var buf_size: integer
): km_kbp_status; cdecl; external kmnkbp0 delayed;

function km_kbp_context_items_to_utf8(
  const item: pkm_kbp_context_item;
  buf: pansichar;
  var buf_size: integer
): km_kbp_status; cdecl; external kmnkbp0 delayed;

procedure km_kbp_context_items_dispose(
  const context_items: km_kbp_context_item
); cdecl; external kmnkbp0 delayed;

function km_kbp_context_set(
  context: pkm_kbp_context;
  context_items: pkm_kbp_context_item
): km_kbp_status; cdecl; external kmnkbp0 delayed;

function km_kbp_context_get(
  context: pkm_kbp_context;
  var context_items: pkm_kbp_context_item
): km_kbp_status; cdecl; external kmnkbp0 delayed;

procedure km_kbp_context_clear(
  context: pkm_kbp_context
); cdecl; external kmnkbp0 delayed;

function km_kbp_context_append(
  context: pkm_kbp_context;
  context_items: pkm_kbp_context_item
): km_kbp_status; cdecl; external kmnkbp0 delayed;

function km_kbp_context_shrink(
  context: pkm_kbp_context;
  num: Integer;
  prefix: pkm_kbp_context_item
): km_kbp_status; cdecl; external kmnkbp0 delayed;



type
  km_kbp_option_scope = (
    KM_KBP_OPT_UNKNOWN      = 0,
    KM_KBP_OPT_KEYBOARD     = 1,
    KM_KBP_OPT_ENVIRONMENT  = 2,
    KM_KBP_OPT_MAX_SCOPES
  );

  km_kbp_option_item = record
    key: pkm_kbp_cp;
    value: pkm_kbp_cp;
    scope: km_kbp_option_scope;
  end;

  pkm_kbp_option_item = ^km_kbp_option_item;

const
  KM_KBP_OPTIONS_END: km_kbp_option_item = (key: nil; value: nil; scope: KM_KBP_OPT_UNKNOWN);


type
  km_kbp_action_type = (
    KM_KBP_IT_END         = 0,  // Marks end of action items list.
    KM_KBP_IT_CHAR        = 1,  // A Unicode character has been generated.
    KM_KBP_IT_MARKER      = 2,  // Correlates to kmn's "deadkey" markers.
    KM_KBP_IT_ALERT       = 3,  // The keyboard has triggered a alert/beep/bell.
    KM_KBP_IT_BACK        = 4,  // Delete the codepoint preceding the insertion point.
    KM_KBP_IT_PERSIST_OPT = 5,  // The indicated option needs to be stored.
    KM_KBP_IT_EMIT_KEYSTROKE = 6,  // Emit the current keystroke to the application
    KM_KBP_IT_INVALIDATE_CONTEXT = 7,
            // The processor requests that the context buffer be cleared;
            // for applications where context is cached, this clears the context;
            // for applications where context is read from the focused text store,
            // the context is just re-read and markers flushed.
    KM_KBP_IT_CAPSLOCK    = 8,  // Enable or disable capsLock
    KM_KBP_IT_MAX_TYPE_ID
  );

  km_kbp_backspace_type = (
    KM_KBP_BT_UNKNOWN    = 0,  // Used at beginning of context; user-initiated backspace
    KM_KBP_BT_CHAR       = 1,  // Deleting a character prior to insertion point
    KM_KBP_BT_MARKER     = 2,  // Deleting a marker prior to insertion point
    KM_KBP_BT_MAX_TYPE_ID
  );

  km_kbp_backspace_item = record
    expected_type: uint8_t;            /// TODO: km_kbp_backspace_type
    expected_value: uintptr_t;         /// used mainly in unit tests
  end;

  km_kbp_action_item = record
    _type: km_kbp_action_type;
{$IFDEF WIN64}
    _reserved: array[0..6] of uint8_t;
{$ELSE}
    _reserved: array[0..2] of uint8_t;
{$ENDIF}
  case Integer of
    0: (marker: uintptr_t);
    1: (option: pkm_kbp_option_item);
    2: (character: km_kbp_usv);
    3: (backspace: km_kbp_backspace_item);
    4: (capsLock: uint8_t);  // CAPSLOCK type, 1 to turn on, 0 to turn off
  end;

  pkm_kbp_action_item = ^km_kbp_action_item;

// These types are used only for debugging convenience
type
  km_kbp_action_item_array = array[0..100] of km_kbp_action_item;
  pkm_kbp_action_item_array = ^km_kbp_action_item_array;

function km_kbp_options_list_size(
  opts: pkm_kbp_option_item
): Integer; cdecl; external kmnkbp0 delayed;

function km_kbp_state_option_lookup(
  state: pkm_kbp_state;
  scope: km_kbp_option_scope;
  key: pkm_kbp_cp;
  var value: pkm_kbp_cp
): km_kbp_status; cdecl; external kmnkbp0 delayed;

function km_kbp_state_options_update(
  state: pkm_kbp_state;
  new_opts: pkm_kbp_option_item
): km_kbp_status; cdecl; external kmnkbp0 delayed;

function km_kbp_state_options_to_json(
  state: pkm_kbp_state;
  buf: PAnsiChar;
  var space: Integer
): km_kbp_status; cdecl; external kmnkbp0 delayed;

type
  km_kbp_keyboard_attrs = record
    version_string: pkm_kbp_cp;
    id: pkm_kbp_cp;
    folder_path: km_kbp_path_name;
    default_optons: pkm_kbp_option_item
  end;

  pkm_kbp_keyboard_attrs = ^km_kbp_keyboard_attrs;

function km_kbp_keyboard_load(
  kb_path: km_kbp_path_name;
  var keyboard: pkm_kbp_keyboard
): km_kbp_status; cdecl; external kmnkbp0 delayed;

procedure km_kbp_keyboard_dispose(
  keyboard: pkm_kbp_keyboard
); cdecl; external kmnkbp0 delayed;

function km_kbp_keyboard_get_attrs(
  keyboard: pkm_kbp_keyboard;
  var out: pkm_kbp_keyboard_attrs
): km_kbp_status; cdecl; external kmnkbp0 delayed;

function km_kbp_state_create(
  keyboard: pkm_kbp_keyboard;
  env: pkm_kbp_option_item;
  var out: pkm_kbp_state
): km_kbp_status; cdecl; external kmnkbp0 delayed;

function km_kbp_state_clone(
  state: pkm_kbp_state;
  var out: pkm_kbp_state
): km_kbp_status; cdecl; external kmnkbp0 delayed;

procedure km_kbp_state_dispose(
  state: pkm_kbp_state
); cdecl; external kmnkbp0 delayed;

function km_kbp_state_context(
  state: pkm_kbp_state
): pkm_kbp_context; cdecl; external kmnkbp0 delayed;

function km_kbp_state_action_items(
  state: pkm_kbp_state;
  num_items: pinteger
): pkm_kbp_action_item; cdecl; external kmnkbp0 delayed;

function km_kbp_state_to_json(
  state: pkm_kbp_state;
  buf: PAnsiChar;
  space: pinteger
): km_kbp_status; cdecl; external kmnkbp0 delayed;

type
  km_kbp_attr = record
    max_context: Integer;   // Maximum context size supported by processor.
    current:     uint16_t;  // Current API number supported.
    revision:    uint16_t;  // Implementation number of current API.
    age:         uint16_t;  // current - age == Oldest API number supported.
    technology : uint16_t;  // A bit field specifiying which Keyboard
                            //  technologies the engine supports.
    vendor: pansichar       // Implementor of the processor.
  end;

  pkm_kbp_attr = ^km_kbp_attr;

  km_kbp_tech_value = (
    KM_KBP_TECH_UNSPECIFIED = 0,
    KM_KBP_TECH_MOCK        = 1 shl 0,
    KM_KBP_TECH_KMX         = 1 shl 1,
    KM_KBP_TECH_LDML        = 1 shl 2,
    KM_KBP_TECH_RUST_MOCK   = 1 shl 3
  );

function km_kbp_get_engine_attrs(
  state: pkm_kbp_state
): pkm_kbp_attr; cdecl; external kmnkbp0 delayed;

function
km_kbp_process_event(
  state: pkm_kbp_state;
  vk: km_kbp_virtual_key;
  modifier_state: uint16_t;
  is_key_down: uint8_t
): km_kbp_status; cdecl; external kmnkbp0 delayed;


// keyboardprocessor_vkeys.h

const
// enum km_kbp_modifier_state - matches Keyman32 shift states
  KM_KBP_MODIFIER_LCTRL       = 1 shl 0;
  KM_KBP_MODIFIER_RCTRL       = 1 shl 1;
  KM_KBP_MODIFIER_LALT        = 1 shl 2;
  KM_KBP_MODIFIER_RALT        = 1 shl 3;
  KM_KBP_MODIFIER_SHIFT       = 1 shl 4;
  KM_KBP_MODIFIER_CTRL        = 1 shl 5;
  KM_KBP_MODIFIER_ALT         = 1 shl 6;
  {
    KM_KBP_MODIFIER_META        = 1 shl 7,    // Either Meta-key flag (tentative).  Not usable by keyboards currently
                                             // Used internally (currently, only by KMW) to ensure Meta-key
                                             // shortcuts safely bypass rules
                                             // Meta key = Command key on macOS, Windows key on Windows
  }
  KM_KBP_MODIFIER_CAPS        = 1 shl 8;
  KM_KBP_MODIFIER_NOCAPS      = 1 shl 9;
  {
    KM_KBP_MODIFIER_NUMLOCK     = 1 << 10,
    KM_KBP_MODIFIER_NONUMLOCK   = 1 << 11,
    KM_KBP_MODIFIER_SCROLLOCK   = 1 << 12,
    KM_KBP_MODIFIER_NOSCROLLOCK = 1 << 13,
    KM_KBP_MODIFIER_VIRTUALKEY  = 1 << 14,
  }

const
// enum km_kbp_modifier_mask
  KM_KBP_MODIFIER_MASK_ALL         = $7f;
  KM_KBP_MODIFIER_MASK_ALT_GR_SIM  = KM_KBP_MODIFIER_LCTRL or KM_KBP_MODIFIER_LALT;
  KM_KBP_MODIFIER_MASK_CHIRAL      = $1f;
  KM_KBP_MODIFIER_MASK_IS_CHIRAL   = $0f;
  KM_KBP_MODIFIER_MASK_NON_CHIRAL  = $7f;
  KM_KBP_MODIFIER_MASK_CAPS        = $0300;
{KM_KBP_MODIFIER_MASK_NUMLOCK     = $0C00,
  KM_KBP_MODIFIER_MASK_SCROLLLOCK  = $3000,}

// These are Windows API VKEYs, using Keyman VKEY names.

const
// enum km_kpb_virtual_key
  KM_KBP_VKEY__00       = $00;
  KM_KBP_VKEY_LBUTTON   = $01;
  KM_KBP_VKEY_RBUTTON   = $02;
  KM_KBP_VKEY_CANCEL    = $03;
  KM_KBP_VKEY_MBUTTON   = $04;
  KM_KBP_VKEY__05   = $05;
  KM_KBP_VKEY__06   = $06;
  KM_KBP_VKEY__07   = $07;
  KM_KBP_VKEY_BKSP   = $08;
  KM_KBP_VKEY_TAB   = $09;
  KM_KBP_VKEY__0A   = $0A;
  KM_KBP_VKEY__0B   = $0B;
  KM_KBP_VKEY_KP5   = $0C;
  KM_KBP_VKEY_ENTER   = $0D;
  KM_KBP_VKEY__0E   = $0E;
  KM_KBP_VKEY__0F   = $0F;
  KM_KBP_VKEY_SHIFT   = $10;
  KM_KBP_VKEY_CONTROL   = $11;
  KM_KBP_VKEY_ALT   = $12;
  KM_KBP_VKEY_PAUSE   = $13;
  KM_KBP_VKEY_CAPS   = $14;
  KM_KBP_VKEY__15   = $15;
  KM_KBP_VKEY__16   = $16;
  KM_KBP_VKEY__17   = $17;
  KM_KBP_VKEY__18   = $18;
  KM_KBP_VKEY__19   = $19;
  KM_KBP_VKEY__1A   = $1A;
  KM_KBP_VKEY_ESC   = $1B;
  KM_KBP_VKEY__1C   = $1C;
  KM_KBP_VKEY__1D   = $1D;
  KM_KBP_VKEY__1E   = $1E;
  KM_KBP_VKEY__1F   = $1F;
  KM_KBP_VKEY_SPACE   = $20;
  KM_KBP_VKEY_PGUP   = $21;
  KM_KBP_VKEY_PGDN   = $22;
  KM_KBP_VKEY_END   = $23;
  KM_KBP_VKEY_HOME   = $24;
  KM_KBP_VKEY_LEFT   = $25;
  KM_KBP_VKEY_UP   = $26;
  KM_KBP_VKEY_RIGHT   = $27;
  KM_KBP_VKEY_DOWN   = $28;
  KM_KBP_VKEY_SEL   = $29;
  KM_KBP_VKEY_PRINT   = $2A;
  KM_KBP_VKEY_EXEC   = $2B;
  KM_KBP_VKEY_PRTSCN   = $2C;
  KM_KBP_VKEY_INS   = $2D;
  KM_KBP_VKEY_DEL   = $2E;
  KM_KBP_VKEY_HELP   = $2F;
  KM_KBP_VKEY_0   = $30;
  KM_KBP_VKEY_1   = $31;
  KM_KBP_VKEY_2   = $32;
  KM_KBP_VKEY_3   = $33;
  KM_KBP_VKEY_4   = $34;
  KM_KBP_VKEY_5   = $35;
  KM_KBP_VKEY_6   = $36;
  KM_KBP_VKEY_7   = $37;
  KM_KBP_VKEY_8   = $38;
  KM_KBP_VKEY_9   = $39;
  KM_KBP_VKEY__3A   = $3A;
  KM_KBP_VKEY__3B   = $3B;
  KM_KBP_VKEY__3C   = $3C;
  KM_KBP_VKEY__3D   = $3D;
  KM_KBP_VKEY__3E   = $3E;
  KM_KBP_VKEY__3F   = $3F;
  KM_KBP_VKEY__40   = $40;
  KM_KBP_VKEY_A   = $41;
  KM_KBP_VKEY_B   = $42;
  KM_KBP_VKEY_C   = $43;
  KM_KBP_VKEY_D   = $44;
  KM_KBP_VKEY_E   = $45;
  KM_KBP_VKEY_F   = $46;
  KM_KBP_VKEY_G   = $47;
  KM_KBP_VKEY_H   = $48;
  KM_KBP_VKEY_I   = $49;
  KM_KBP_VKEY_J   = $4A;
  KM_KBP_VKEY_K   = $4B;
  KM_KBP_VKEY_L   = $4C;
  KM_KBP_VKEY_M   = $4D;
  KM_KBP_VKEY_N   = $4E;
  KM_KBP_VKEY_O   = $4F;
  KM_KBP_VKEY_P   = $50;
  KM_KBP_VKEY_Q   = $51;
  KM_KBP_VKEY_R   = $52;
  KM_KBP_VKEY_S   = $53;
  KM_KBP_VKEY_T   = $54;
  KM_KBP_VKEY_U   = $55;
  KM_KBP_VKEY_V   = $56;
  KM_KBP_VKEY_W   = $57;
  KM_KBP_VKEY_X   = $58;
  KM_KBP_VKEY_Y   = $59;
  KM_KBP_VKEY_Z   = $5A;
  KM_KBP_VKEY__5B   = $5B;
  KM_KBP_VKEY__5C   = $5C;
  KM_KBP_VKEY__5D   = $5D;
  KM_KBP_VKEY__5E   = $5E;
  KM_KBP_VKEY__5F   = $5F;
  KM_KBP_VKEY_NP0   = $60;
  KM_KBP_VKEY_NP1   = $61;
  KM_KBP_VKEY_NP2   = $62;
  KM_KBP_VKEY_NP3   = $63;
  KM_KBP_VKEY_NP4   = $64;
  KM_KBP_VKEY_NP5   = $65;
  KM_KBP_VKEY_NP6   = $66;
  KM_KBP_VKEY_NP7   = $67;
  KM_KBP_VKEY_NP8   = $68;
  KM_KBP_VKEY_NP9   = $69;
  KM_KBP_VKEY_NPSTAR   = $6A;
  KM_KBP_VKEY_NPPLUS   = $6B;
  KM_KBP_VKEY_SEPARATOR   = $6C;
  KM_KBP_VKEY_NPMINUS   = $6D;
  KM_KBP_VKEY_NPDOT   = $6E;
  KM_KBP_VKEY_NPSLASH   = $6F;
  KM_KBP_VKEY_F1   = $70;
  KM_KBP_VKEY_F2   = $71;
  KM_KBP_VKEY_F3   = $72;
  KM_KBP_VKEY_F4   = $73;
  KM_KBP_VKEY_F5   = $74;
  KM_KBP_VKEY_F6   = $75;
  KM_KBP_VKEY_F7   = $76;
  KM_KBP_VKEY_F8   = $77;
  KM_KBP_VKEY_F9   = $78;
  KM_KBP_VKEY_F10   = $79;
  KM_KBP_VKEY_F11   = $7A;
  KM_KBP_VKEY_F12   = $7B;
  KM_KBP_VKEY_F13   = $7C;
  KM_KBP_VKEY_F14   = $7D;
  KM_KBP_VKEY_F15   = $7E;
  KM_KBP_VKEY_F16   = $7F;
  KM_KBP_VKEY_F17   = $80;
  KM_KBP_VKEY_F18   = $81;
  KM_KBP_VKEY_F19   = $82;
  KM_KBP_VKEY_F20   = $83;
  KM_KBP_VKEY_F21   = $84;
  KM_KBP_VKEY_F22   = $85;
  KM_KBP_VKEY_F23   = $86;
  KM_KBP_VKEY_F24   = $87;
  KM_KBP_VKEY__88   = $88;
  KM_KBP_VKEY__89   = $89;
  KM_KBP_VKEY__8A   = $8A;
  KM_KBP_VKEY__8B   = $8B;
  KM_KBP_VKEY__8C   = $8C;
  KM_KBP_VKEY__8D   = $8D;
  KM_KBP_VKEY__8E   = $8E;
  KM_KBP_VKEY__8F   = $8F;
  KM_KBP_VKEY_NUMLOCK   = $90;
  KM_KBP_VKEY_SCROLL   = $91;
  KM_KBP_VKEY__92   = $92;
  KM_KBP_VKEY__93   = $93;
  KM_KBP_VKEY__94   = $94;
  KM_KBP_VKEY__95   = $95;
  KM_KBP_VKEY__96   = $96;
  KM_KBP_VKEY__97   = $97;
  KM_KBP_VKEY__98   = $98;
  KM_KBP_VKEY__99   = $99;
  KM_KBP_VKEY__9A   = $9A;
  KM_KBP_VKEY__9B   = $9B;
  KM_KBP_VKEY__9C   = $9C;
  KM_KBP_VKEY__9D   = $9D;
  KM_KBP_VKEY__9E   = $9E;
  KM_KBP_VKEY__9F   = $9F;
  KM_KBP_VKEY__A0   = $A0;
  KM_KBP_VKEY__A1   = $A1;
  KM_KBP_VKEY__A2   = $A2;
  KM_KBP_VKEY__A3   = $A3;
  KM_KBP_VKEY__A4   = $A4;
  KM_KBP_VKEY__A5   = $A5;
  KM_KBP_VKEY__A6   = $A6;
  KM_KBP_VKEY__A7   = $A7;
  KM_KBP_VKEY__A8   = $A8;
  KM_KBP_VKEY__A9   = $A9;
  KM_KBP_VKEY__AA   = $AA;
  KM_KBP_VKEY__AB   = $AB;
  KM_KBP_VKEY__AC   = $AC;
  KM_KBP_VKEY__AD   = $AD;
  KM_KBP_VKEY__AE   = $AE;
  KM_KBP_VKEY__AF   = $AF;
  KM_KBP_VKEY__B0   = $B0;
  KM_KBP_VKEY__B1   = $B1;
  KM_KBP_VKEY__B2   = $B2;
  KM_KBP_VKEY__B3   = $B3;
  KM_KBP_VKEY__B4   = $B4;
  KM_KBP_VKEY__B5   = $B5;
  KM_KBP_VKEY__B6   = $B6;
  KM_KBP_VKEY__B7   = $B7;
  KM_KBP_VKEY__B8   = $B8;
  KM_KBP_VKEY__B9   = $B9;
  KM_KBP_VKEY_COLON   = $BA;
  KM_KBP_VKEY_EQUAL   = $BB;
  KM_KBP_VKEY_COMMA   = $BC;
  KM_KBP_VKEY_HYPHEN   = $BD;
  KM_KBP_VKEY_PERIOD   = $BE;
  KM_KBP_VKEY_SLASH   = $BF;
  KM_KBP_VKEY_BKQUOTE   = $C0;
  KM_KBP_VKEY__C1   = $C1;
  KM_KBP_VKEY__C2   = $C2;
  KM_KBP_VKEY__C3   = $C3;
  KM_KBP_VKEY__C4   = $C4;
  KM_KBP_VKEY__C5   = $C5;
  KM_KBP_VKEY__C6   = $C6;
  KM_KBP_VKEY__C7   = $C7;
  KM_KBP_VKEY__C8   = $C8;
  KM_KBP_VKEY__C9   = $C9;
  KM_KBP_VKEY__CA   = $CA;
  KM_KBP_VKEY__CB   = $CB;
  KM_KBP_VKEY__CC   = $CC;
  KM_KBP_VKEY__CD   = $CD;
  KM_KBP_VKEY__CE   = $CE;
  KM_KBP_VKEY__CF   = $CF;
  KM_KBP_VKEY__D0   = $D0;
  KM_KBP_VKEY__D1   = $D1;
  KM_KBP_VKEY__D2   = $D2;
  KM_KBP_VKEY__D3   = $D3;
  KM_KBP_VKEY__D4   = $D4;
  KM_KBP_VKEY__D5   = $D5;
  KM_KBP_VKEY__D6   = $D6;
  KM_KBP_VKEY__D7   = $D7;
  KM_KBP_VKEY__D8   = $D8;
  KM_KBP_VKEY__D9   = $D9;
  KM_KBP_VKEY__DA   = $DA;
  KM_KBP_VKEY_LBRKT   = $DB;
  KM_KBP_VKEY_BKSLASH   = $DC;
  KM_KBP_VKEY_RBRKT   = $DD;
  KM_KBP_VKEY_QUOTE   = $DE;
  KM_KBP_VKEY_oDF   = $DF;
  KM_KBP_VKEY_oE0   = $E0;
  KM_KBP_VKEY_oE1   = $E1;
  KM_KBP_VKEY_oE2   = $E2; // 102nd key on European layouts
  KM_KBP_VKEY_oE3   = $E3;
  KM_KBP_VKEY_oE4   = $E4;
  KM_KBP_VKEY__E5   = $E5;
  KM_KBP_VKEY_oE6   = $E6;
  KM_KBP_VKEY__E7   = $E7;
  KM_KBP_VKEY__E8   = $E8;
  KM_KBP_VKEY_oE9   = $E9;
  KM_KBP_VKEY_oEA   = $EA;
  KM_KBP_VKEY_oEB   = $EB;
  KM_KBP_VKEY_oEC   = $EC;
  KM_KBP_VKEY_oED   = $ED;
  KM_KBP_VKEY_oEE   = $EE;
  KM_KBP_VKEY_oEF   = $EF;
  KM_KBP_VKEY_oF0   = $F0;
  KM_KBP_VKEY_oF1   = $F1;
  KM_KBP_VKEY_oF2   = $F2;
  KM_KBP_VKEY_oF3   = $F3;
  KM_KBP_VKEY_oF4   = $F4;
  KM_KBP_VKEY_oF5   = $F5;
  KM_KBP_VKEY__F6   = $F6;
  KM_KBP_VKEY__F7   = $F7;
  KM_KBP_VKEY__F8   = $F8;
  KM_KBP_VKEY__F9   = $F9;
  KM_KBP_VKEY__FA   = $FA;
  KM_KBP_VKEY__FB   = $FB;
  KM_KBP_VKEY__FC   = $FC;
  KM_KBP_VKEY__FD   = $FD;
  KM_KBP_VKEY__FE   = $FE;
  KM_KBP_VKEY__FF   = $FF;

// keyboardprocessor_consts.h
const
  // Defined environment options for KMX processor
  KM_KBP_KMX_ENV_PLATFORM                       = 'platform';
  KM_KBP_KMX_ENV_BASELAYOUT                     = 'baseLayout';
  KM_KBP_KMX_ENV_BASELAYOUTALT                  = 'baseLayoutAlt';
  KM_KBP_KMX_ENV_SIMULATEALTGR                  = 'simulateAltgr';
  KM_KBP_KMX_ENV_CAPSLOCK                       = 'capsLock';
  KM_KBP_KMX_ENV_BASELAYOUTGIVESCTRLRALTFORRALT = 'baseLayoutGivesCtrlRAltForRAlt';

procedure _km_kbp_set_library_path(const path: string);

implementation

uses
  System.SysUtils,
  Winapi.Windows;

procedure _km_kbp_set_library_path(const path: string);
begin
  if LoadLibrary(PChar(path)) = 0 then
    RaiseLastOSError;
end;

end.
