From 28318762d1da31d23d53ef321555e4ec590ff392 Mon Sep 17 00:00:00 2001 From: "Evgeny Grechnikov (Diamond)" Date: Sun, 20 Dec 2009 23:35:51 +0000 Subject: [PATCH] libini: ini_get_shortcut added git-svn-id: svn://kolibrios.org@1327 a494cfbc-eb01-0410-851d-a64ba20cac60 --- .../libraries/libs-dev/libini/libini.asm | 212 +++++++++++++++++- .../libraries/libs-dev/libini/libini_p.asm | 58 +++++ 2 files changed, 267 insertions(+), 3 deletions(-) diff --git a/programs/develop/libraries/libs-dev/libini/libini.asm b/programs/develop/libraries/libs-dev/libini/libini.asm index f7e544cf69..e54c5f7add 100644 --- a/programs/develop/libraries/libs-dev/libini/libini.asm +++ b/programs/develop/libraries/libs-dev/libini/libini.asm @@ -64,7 +64,7 @@ public @EXPORT as 'EXPORTS' include '../../../../proc32.inc' include '../../../../macros.inc' include '../libio/libio.inc' -purge section ; mov,add,sub +purge section,mov,add,sub include 'libini_p.inc' @@ -657,6 +657,211 @@ endl ret endp +;;================================================================================================;; +proc ini.get_shortcut _f_name, _sec_name, _key_name, _def_val, _modifiers ;///////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? Read shortcut key ;; +;;------------------------------------------------------------------------------------------------;; +;> _f_name = ini filename ;; +;> _sec_name = section name ;; +;> _key_name = key name ;; +;> _def_val = default value to return if no key, section or file found ;; +;> _modifiers = pointer to dword variable which receives modifiers state as in 66.4 ;; +;;------------------------------------------------------------------------------------------------;; +;< eax = [_def_val] (error) / shortcut key value as scancode ;; +;< [[_modifiers]] = unchanged (error) / modifiers state for this shortcut ;; +;;================================================================================================;; +locals + buf rb 64 +endl + + push ebx esi edi + + lea esi, [buf] + stdcall ini.get_str, [_f_name], [_sec_name], [_key_name], esi, 64, 0 + cmp byte[esi],0 + je .exit_error + + xor ebx, ebx ; ebx holds the value of modifiers +.loop: +; test for end + xor eax, eax + cmp byte [esi], al + jz .exit_ok ; exit with scancode zero +; skip all '+'s + cmp byte [esi], '+' + jnz @f + inc esi + jmp .loop +@@: +; test for names + mov edi, .names_table + xor edx, edx +.names_loop: + movzx ecx, byte [edi] + inc edi + push esi +@@: + lodsb + or al, 20h + scasb + loopz @b + jz .name_found + pop esi + lea edi, [edi+ecx+4] + inc edx + cmp byte [edi], 0 + jnz .names_loop +; special test: functional keys F + cmp byte [esi], 'f' + jz @f + cmp byte [esi], 'F' + jnz .no_fx +@@: + mov edi, esi + inc esi + call libini._.str_to_int + test eax, eax + jz .fx + mov esi, edi +.no_fx: +; name not found, that must be usual key + movzx eax, byte [esi] + stdcall libini._.ascii_to_scan, eax + test eax, eax + jz .exit_error +; all is ok +.exit_ok: + mov ecx, [_modifiers] + test ecx, ecx + jz @f + mov [ecx], ebx + +@@: + + pop edi esi ebx + ret + +.exit_error: + mov eax, [_def_val] + pop edi esi ebx + ret +; handler for Fx +; eax = number +.fx: + cmp eax, 10 + ja @f + add eax, 3Bh-1 + jmp .exit_ok +@@: + add eax, 57h-11 + jmp .exit_ok +; handlers for names +.name_found: + pop eax ; ignore saved esi + call dword [edi] + cmp edx, .num_modifiers + jae .exit_ok + jmp .loop +; modifiers +; syntax of value for each modifier: +; 0 = none, 1 = exactly one of L+R, 2 = both L+R, 3 = L, 4 = R +; Logic for switching: LShift+RShift=LShift+Shift=Shift+Shift, LShift+LShift=LShift +; generic modifier: 0->1->2->2, 3->2, 4->2 +; left modifier: 0->3->3, 1->2->2, 4->2 +; right modifier: 0->4->4, 1->2->2, 3->2 +; Shift corresponds to first hex digit, Ctrl - second, Alt - third +macro shortcut_handle_modifiers name,reg,shift +{ +local .set2,.set3,.set4 +.#name#_handler: ; generic modifier + test reg, 0xF + jnz .set2 +if shift + or reg, 1 shl shift +else + inc reg +end if + retn +.set2: + and reg, not (0xF shl shift) + or reg, 2 shl shift + retn +.l#name#_handler: + mov al, reg + and al, 0xF shl shift + jz .set3 + cmp al, 3 shl shift + jnz .set2 + retn +.set3: + add reg, 3 shl shift + retn +.r#name#_handler: + mov al, reg + and al, 0xF shl shift + jz .set4 + cmp al, 4 shl shift + jnz .set2 + retn +.set4: + add reg, 4 shl shift + retn +} +shortcut_handle_modifiers shift,bl,0 +shortcut_handle_modifiers ctrl,bl,4 +shortcut_handle_modifiers alt,bh,0 +; names of keys +.name_handler: + movzx eax, byte [.names_scancodes+edx-.num_modifiers] + retn +endp + +; note: comparison ignores case, so this table keeps lowercase names +; macro does this +macro shortcut_name_with_handler name,handler +{ +local .start, .end + db .end - .start +.start: + db name +.end: +repeat .end - .start + load .a byte from .start + % - 1 + store byte .a or 0x20 at .start + % - 1 +end repeat + dd handler +} +macro shortcut_name [name] +{ + shortcut_name_with_handler name, .name_handler +} +; all names here must be in english +; ... or modify lowercasing in macro and in comparison +.names_table: +; generic modifiers + shortcut_name_with_handler 'Ctrl', .ctrl_handler + shortcut_name_with_handler 'Alt', .alt_handler + shortcut_name_with_handler 'Shift', .shift_handler +; concrete modifiers + shortcut_name_with_handler 'LCtrl', .lctrl_handler + shortcut_name_with_handler 'RCtrl', .rctrl_handler + shortcut_name_with_handler 'LAlt', .lalt_handler + shortcut_name_with_handler 'RAlt', .ralt_handler + shortcut_name_with_handler 'LShift', .lshift_handler + shortcut_name_with_handler 'RShift', .rshift_handler +.num_modifiers = 9 +; symbolic names of keys + shortcut_name 'Home', 'End', 'PgUp', 'PgDn', 'Ins', 'Insert', 'Del', 'Delete' + shortcut_name 'Tab', 'Plus', 'Esc', 'Enter', 'Backspace', 'Space', 'Left', 'Right' + shortcut_name 'Up', 'Down' +; end of table + db 0 +ini.get_shortcut.names_scancodes: +; scancodes for 'Home' ... 'Down' + db 47h, 4Fh, 49h, 51h, 52h, 52h, 53h, 53h + db 0Fh, 4Eh, 01h, 1Ch, 0Eh, 39h, 4Bh, 4Dh + db 48h, 50h ;;================================================================================================;; ;;////////////////////////////////////////////////////////////////////////////////////////////////;; @@ -699,7 +904,7 @@ align 16 export \ libini._.init , 'lib_init' , \ - 0x00080008 , 'version' , \ + 0x00080009 , 'version' , \ ini.enum_sections , 'ini_enum_sections' , \ ini.enum_keys , 'ini_enum_keys' , \ ini.get_str , 'ini_get_str' , \ @@ -707,4 +912,5 @@ export \ ini.get_color , 'ini_get_color' , \ ini.set_str , 'ini_set_str' , \ ini.set_int , 'ini_set_int' , \ - ini.set_color , 'ini_set_color' + ini.set_color , 'ini_set_color' , \ + ini.get_shortcut , 'ini_get_shortcut' diff --git a/programs/develop/libraries/libs-dev/libini/libini_p.asm b/programs/develop/libraries/libs-dev/libini/libini_p.asm index 659160c943..d358dae76c 100644 --- a/programs/develop/libraries/libs-dev/libini/libini_p.asm +++ b/programs/develop/libraries/libs-dev/libini/libini_p.asm @@ -621,3 +621,61 @@ proc libini._.int_to_str ;////////////////////////////////////////////////////// stosb retn endp + +;;================================================================================================;; +proc libini._.ascii_to_scan ;_ascii_code ;////////////////////////////////////////////////////////;; +;;------------------------------------------------------------------------------------------------;; +;? Translate ASCII code of key to scancode using standard mapping from keymap.key ;; +;;------------------------------------------------------------------------------------------------;; +;> _ascii_code = [esp+4] = ASCII code to convert ;; +;;------------------------------------------------------------------------------------------------;; +;< eax = 0 (error) / scancode (success) ;; +;;================================================================================================;; +; /sys/keymap.key + sub esp, 256 + mov eax, esp + push ebx + push 'key' + push 'map.' + push '/key' + push '/sys' + push eax ; buffer in the stack + push 0x100 ; read 0x100 bytes + push 0 + push 0 ; from position zero + push 0 ; subfunction: read + mov ebx, esp + push 70 + pop eax + mcall + add esp, 36 + pop ebx + test eax, eax + jnz .die + mov al, [esp+256+4] ; get ASCII code + push edi +; first keytable - no modifiers pressed +; check scancodes from 1 to 36h (inclusive) + lea edi, [esp+4+1] + mov edx, edi + mov ecx, 36h + repnz scasb + jz .found +; second keytable - Shift pressed + lea edi, [esp+4+128+1] + mov edx, edi + mov ecx, 36h + repnz scasb + jz .found + pop edi +.die: + xor eax, eax + jmp .ret +.found: + mov eax, edi + sub eax, edx + pop edi +.ret: + add esp, 256 + ret 4 +endp