I am writing a virtual keyboard application that reads windows KBD file to build the keyboard. I am having trouble understanding how to interpret the array of characters returned for each virtual key.
I am using the kbd.h files in this CodePlex project.
Here is the struct that I am not understanding.
typedef struct {
PVK_TO_BIT pVkToBit; // Virtual Keys -> Mod bits
WORD wMaxModBits; // max Modification bit combination value
BYTE ModNumber[]; // Mod bits -> Modification Number
} MODIFIERS, *KBD_LONG_POINTER PMODIFIERS;
When reading the documentation, and analyzing the results with a US keyboard, this struct and its contained data makes sense.
---------------
US
---------------
CharModifiers
0001 = SHIFT
0010 = CTRL
0100 = ALT
ModNumber
0000 = 0 = BASE
0001 = 1 = SHIFT
0010 = 2 = CTRL
0011 = 3 = SHIFT + CTRL
What this says is that for the array of characters returned for each virtual key (another kbd.h struct), the first one represents no modifiers, the second represents the value when SHIFT is held, and so on. This is accurate and maps perfectly to the array of characters returned for each virtual key.
However, if I load a German keyboard layout (KBDGR.dll), the PMODIFIERS doesn't line up with array of characters returned for each virtual key.
---------------
German
---------------
CharModifiers
0001 = SHIFT
0010 = CTRL
0100 = ALT
ModNumber
0000 = 0 = BASE = REALLY BASE
0001 = 1 = SHIFT = REALLY SHIFT
0011 = 3 = SHIFT + CTRL = REALLY ALTGR
0100 = 4 = ALT = REALLY CTRL
1111 = 15 = INVALID = INVALID
1111 = 15 = INVALID = INVALID
0010 = 2 = CTRL = REALLY SHIFT + CTRL
0101 = 5 = SHIFT + ALT = REALLY SHIFT + ALTGR
As you can see here, for example, 0010 should correlate with just a CTRL modifier, however, the character returned from the virtual key really represents SHIFT + CTRL.
What am I not understanding? I thought that the array of ModNumber describes each index of characters for each virtual key, and the modifier keys they represent. This assumption worked correctly for the US keyboard layout, but when not for the German keyboard layout?
I emailed the makers of KbdEdit for their input, and they just replied with the answer!
The zero-based position within ModNumber array defines the modifier
combination: eg, the last element "2" is at position 6, whose binary
representation is 110, ie KBDCTRL | KBDALT, ie AltGr
(www.kbdedit.com/manual/low_level_modifiers.html#AltGr) The value "2"
means that AltGr mappings will appear at index 2 in all aVkToWchX[]
arrays (for X>=3).
The position 3 corresponds to Shift+Ctrl (= 011 =
KBDSHIFT | KBDCTRL) - you see that this combination is to be found at
aVkToWchX[4] (for X>=5)
If you open the German layout in KbdEdit,
you will see that indeed AltGr is at position 2, and Shift+Ctrl at
position 4 (zero based) - see attached screenshot.
Hope this helps.
Regards,
Ivica
Thanks Ivica!
I've never figured out this either :) The description in the kbd.h-file didn't make much sense either, so I didn't bother to understand it.
In the kbd.h-header it states:
* CONTROL MENU SHIFT
* ^ ^ ^
* aModification[] = { | | |
* 0, // 0 0 0 = 000 (none)
I belive the modifiers should be:
001 = SHIFT
010 = ALT
100 = CTRL
I agree that the list seems unlogical based in the german, and I reproduced it.
But I worked mostly on figuring out the connection between scan codes (physical placement) and virtual keys. Each virtual keys have the modifier included, that way you could iterate between all modifier combinations.
Since I'm Norwegian I handled the KBDNO.dll first, comparing it to the MKLC: http://msdn.microsoft.com/en-us/goglobal/bb964665.aspx
Since you asked for the German keyboard I also compared it, and it seems to match. Same with US.
Check out my "virtual keyboard" on my site: http://lars.werner.no/?page_id=922
The CKLL-class could help you a lot to achieve what you are trying to do. The class isn't perfect, so you have to put in some hours to get it there. Look at the keyboard as a array of scancodes with attached virtual keys based on modifiers :)
Sorry for not being more helpful atm, but it has been a while since I even programmed. To little spare time for my hobby!
Related
This challenge in Hackerrank is to shift the string using Julia(programming language( and return the string. I have a function that takes in 3 arguments.
shiftStrings("string", leftShifts, rightShifts)
Left Shift: A single circular rotation of the string in which the first character becomes the last character and all other characters are shifted one index to the left. For example, abcde becomes bcdea after 1 left shift and cdeab after 2 left shifts.
Right Shift: A single circular rotation of the string in which the last character becomes the first character and all other characters are shifted to the right. For example, abcde becomes eabcd after 1 right shift and deabc after 2 right shifts.
I passed only 3 out of 13 test cases. Here is my solution. Please let me know the better solution.
Please refer this, they have done by python
How to shift characters in a string? - Hackerrank challenge
If you take a look at the question you linked they already had an answer to that in python.
def getShiftedString(s, leftShifts, rightShifts):
i = (leftShifts - rightShifts) % len(s)
return s[i:] + s[:i]
If you want to shift a string to the right and then to the left you just need the difference of both. I.e. if you shift 3 to the right and 3 to the left it's like you didn't change anything. "abcde" 3 to the left -> "deabc" 3 to the right -> "abcde".
Therefore, this leads to:
function shiftStrings(str, l, r)
i = mod(l - r, length(str))
str[i+1:end] * str[1:i]
end
Note:
i is the total amount of leftshifts (you take the modulo of leftshifts minus the rightshifts)
Python indexing starts from 0, whereas Julia indexing starts from 1, while modulo returns a 0 if l-r==0, that's why [i+1:end] and [1:i]
If you have Utf8 encoding then you can formulate it like this:
function shiftStrings(str, l, r)
i = mod(l - r, length(str))
indices = collect(eachindex(str))
str[indices[i+1]:end] * str[1:indices[i]]
end
Utf8 characters do not correspond to 1 byte per character, that's why the character indices are different that the String indices. (String indexing starts at every new byte, but some characters like the German "ö" need more than 1 byte)
function getShiftedString(s, leftShifts, rightShifts)
len=length(s)
lr=mod(leftShifts,len)
rr=len-mod(rightShifts,len)
ls1=SubString(s,lr+1,length(s))
ls2=SubString(s,1,lr)
ls=ls1*ls2
rs1=SubString(ls,rr+1,length(s))
rs2=SubString(ls,1,rr)
rs=rs1*rs2
end
I regularly code in R, and I just realized how much of a pain it is for me to move my hand down to the arrow keys and then back to they letters on the keyboard. In Rstudio, I have to do this regularly because the studio completes certain synax automatically, (like parentheses and quotation marks) and then I have to press the arrow key to move out of the parentheses (or quotation marks), this then removed any possible advantage from having R complete the syntax for me. This is extra costly for me because I'm left handed. Is there a shortcut for the arrow keys that's closer to the letter keys?
Intro
To do this, you have two approaches in front:
use your own code
use 3rd party softwares
In these answer I introduce the most efficient and easy approach so for some OSs it's easy and efficient to write your own code while in others it's not really efficient and need a harsh work which have no achivement but wasting time
Windows users
In this method you will use:
alt+I instead of ↑
alt+K instead of ↓
alt+J instead of ←
alt+L instead of →
In order to use this feature, these are the steps in your way:
Download and install autohotkey
Right-click in your desktop area then go to new and make a new "notepad" file
Open empty notepad file and copy/paste codes below into that
Rename your notepad file eveything you want but with *.ahk format
Click your file to run your script
Now you can enjoy and never use arrow keys again...
; #Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
; AHK Command ; key = Effect (Description)
; ALT Keypress Implied for all below
!i::Send {UP} ; i UP (Cursor up line)
!k::Send {DOWN} ; k DOWN (Cursor down line)
!j::Send {LEFT} ; j LEFT (Cursor left one character)
!l::Send {RIGHT} ; l RIGHT (Cursor right one character)
!h::Send {HOME} ; h ALT + RIGHT (Cursor to beginning of line)
!;::Send {END} ; ; ALT + LEFT (Cursor to end of line)
!u::Send ^{HOME} ; h SHIFT + HOME (Cursor to beginning of document)
!o::Send ^{END} ; o SHIFT + END (Cursor to end of document)
; CTRL + ALT Keypress Implied for all below
!^j::Send ^{LEFT} ; j CTRL + LEFT (Cursor left per word)
!^l::Send ^{RIGHT} ; l CTRL + RIGHT (Cursor right per word)
; SHIFT + ALT Keypress Implied for all below
!+i::Send +{UP} ; i SHIFT + UP (Highlight per line)
!+k::Send +{DOWN} ; k SHIFT + DOWN (Highlight per line)
!+j::Send +{LEFT} ; j SHIFT + LEFT (Highlight per character)
!+l::Send +{RIGHT} ; l SHIFT + RIGHT (Highlight per character)
!+h::Send +{HOME} ; h SHIFT + ALT + LEFT (Highlight to beginning of line)
!+;::Send +{END} ; ; SHIFT + ALT + RIGHT (Hightlight to end of line)
!+u::Send ^+{HOME} ; u SHIFT + CTRL + HOME (Highlight to beggininng of document)
!+o::Send ^+{END} ; o SHIFT + CTRL + END (Hightlight to end of document)
; SHIFT + CTRL + ALT Keypress Implied for all below
!+^j::Send +^{LEFT} ; j SHIFT + CTRL + LEFT (Highlight per word)
!+^l::Send +^{RIGHT} ; l SHIFT + CTRL + RIGHT (Hightlight per word)
!+^i::Send +!{UP} ; i SHIFT + ALT + UP (Multiply cursor up)
!+^k::Send +!{DOWN} ; k SHIFT + ALT + DOWN (Multiply cursor down)
; CTRL + SHIFT Keypress Implied for all below
+^i::Send +^{UP}
+^k::Send +^{DOWN}
Important Notes
To use autohotkey script which you made, every time you turn on computer instead of clicking on your script every time, you can copy your script in startup folder.
How to find startup folder?
win+R
type: shell:startup
copy your script into that Folder
MacOS users
In this method you will use
option+I instead of ↑
option+K instead of ↓
option+J instead of ←
option+L instead of →
Use hammerspoon: Is a tremendous tool for many purposes (not just assign a keybinding, for example you can use it for windows sanping or ...) and I think that is one of the MUST-HAVE tools in any macos
Since the documentation of hammerspoon is very very straightforward, I just put the code here and you can install and config hammerspoon from it's Getting Started with Hammerspoon
hs.hotkey.bind({"alt"}, "I", function()
hs.eventtap.keyStroke({}, "up")
end)
hs.hotkey.bind({"alt"}, "K", function()
hs.eventtap.keyStroke({}, "down")
end)
hs.hotkey.bind({"alt"}, "J", function()
hs.eventtap.keyStroke({}, "left")
end)
hs.hotkey.bind({"alt"}, "L", function()
hs.eventtap.keyStroke({}, "right")
end)
Important Notes
If you think hammerspoon is slow or not working as genius as you want another option is Karabiner
Debian-based Linux users (not Ubuntu; see important notes):
In this method you will use:
CapsLock+I instead of ↑
CapsLock+K instead of ↓
CapsLock+J instead of ←
CapsLock+L instead of →
and
alt_gr instead of CapsLock
How? Well:
open up Terminal, write your keyboard layout on in a file(I named it modmap), then open that file and edit it as you will follow next steps:
xmodmap -pke > modmap
gedit modmap
change keyCode 108 (alt_Gr/ISO_Level3_Shift) value, so it should be like this after modifying:
keycode 108 = Caps_Lock Caps_Lock Caps_Lock Caps_Lock Caps_Lock Caps_Lock
change keyCode 66 (CapsLock) value, so it should be like this after modifying:
keycode 66 = Mode_switch Mode_switch Mode_switch Mode_switch Mode_switch Mode_switch
change keyCode 31 (i) value, so it should be like this after modifying:
keycode 31 = i I Up NoSymbol NoSymbol NoSymbol NoSymbol NoSymbol
change keyCode 44 (j) value, so it should be like this after modifying:
keycode 44 = j J Left NoSymbol NoSymbol NoSymbol NoSymbol NoSymbol
change keyCode 45 (k) value, so it should be like this after modifying:
keycode 45 = k K Down NoSymbol NoSymbol NoSymbol NoSymbol NoSymbol
change keyCode 46 (l) value, so it should be like this after modifying:
keycode 46 = l L Right NoSymbol NoSymbol NoSymbol NoSymbol NoSymbol
Important Notes
xmodmap is no longer used/supported on Ubuntu (because it wasn't handy for many users, I think they stop using xmodmap from 2013) but since this is a professional question for very fast coding and working with computer and also coding, I see many professionals using Debian or their own debian-based Linux (not Ubuntu) and they always prefer native solutions to plugins or...
Anyway if you are using Ubuntu you can use xkb or gnome tweak tools where you maybe can adjust your keyboard mapping in a GUI
You can't use this solution easily if you got multi langs/inputs on your keyboard, but you can use it like below:
CapsLock+shift+i instead of ↑
CapsLock+shift+k instead of ↓
CapsLock+shift+j instead of ←
CapsLock+shift+l instead of →
for example, if you also want to have persian_language_input you can do step 1,2,3 above then change other steps like below:
keycode 31 = i I Arabic_heh Up 5 6 7 8
keycode 44 = j J Arabic_teh Left 5 6 7 8
keycode 45 = k K Arabic_noon Down 5 6 7 8
keycode 46 = l L Arabic_meem Right 5 6 7 8
be careful that you shouldn't test above keyboard shortcuts in Terminal
Since we're using xmodmap tool (because it's native unlike xkb), You can only change the AltGr keysyms for keycodes that are already using AltGr. So we change it with CapsLock to overcome this problem since CapsLock is more comfort for fingers to find it is a very acceptable solution.
In most cases, alt_Gr is the right alt Key on your keyboard
further reading about xmodmap on ArchWiki
if anyone has knowledge about this answer in BSD OS (or BSD-BASED) I'll appreciate that if he/she add it to my answer
Two weeks back Microsoft launched "Power Toys" in the Microsoft Store.
You can use the keyboard manager to create a shortcut for arrow keys as mentioned in answer.
I use the vim shortcut for arrow keys as shown below:
[added shortcuts for arrow keys][1]
[1]: https://i.stack.imgur.com/F9syJ.png
I have the same pain, I've tried to use hjkl as arrow keys, and some layout like fun plus wsad. But now I have gotten the best solution since I got a Filco Minila-R. It divided space key into three keys, two function on two sides of sapce key. Like when I type right arrow, I hold the left fn key (at the left side of space) with my left hand thumb while touch F key, F key always used for locating for left hand.
e-d-f-s plus left function keys achived up-down-right-left, right function plus jm-k,-l. achived ins del-home end-pu pd.
If I use capslock + hjkl, I have to use two hands, Minila-R layout allows me using one sigle hand to touch this keys, besides, the two functions which devided from space key just at the most fine place for thumb to touch.
My first hour with the (fascinating) J language, and things are looking good, but I've met my first problem I can't analyse with the help of the documentation.
How to count characters in a string:
y =. 'hello world'
(~. y) ; " 0 (+/ " 1 =y)
┌─┬─┐
│h│1│
├─┼─┤
│e│1│
├─┼─┤
│l│3│
├─┼─┤
│o│2│
├─┼─┤
│ │1│
├─┼─┤
│w│1│
├─┼─┤
│r│1│
├─┼─┤
│d│1│
└─┴─┘
But how can I lose the boxes? I gather that ; joins two items in a horizontal box, but it seems hard to do this without the box characters. How do I get:
h 1
e 1
l 3
and so on? Is it a presentation option?
Well, for starters you must note that you can't group in a matrix elements of different types. The boxing here helps because it puts all elements on the same foot: all boxes.
One thing you can do is format (":) to text and stitch (,.) instead of link (;):
(~.y),. (2 ": "0 +/ "1 = y)
The 2 in 2 ": serves as a format indicator, 2 digits-wide, padded with a blank space.
UPDATE:
Or in the style of Eelvex:
({. , 2&":&#) /. ~ y
There's a few elements that might be new here. Using append (,) instead of stitch (,.) because each result of key (/.) is produced separately, we're not sticking two arrays side by side, but rather creating one big array one row at a time.
There was a popular game at Nov 11th among Chinese programmers. The ninth question is quite hard(sorry but that url contains MD5 and session for that I can paste it here). There was some guides writtern in Chinese with English keywords.
And someone even tried to solve that with one line of Haskell...
So, the question:
given a string looks like this, and get the key to the next question:
01001000 00110100 01110011 01001001 01000001 01000011 01001010 01001011
01101110 01101100 01000001 01000001 01000001 00101011 00110001 01011010
01000010 00110001
I copyed the whole binary string into a gist here: https://gist.github.com/4054140
According to the guides, the binary code can be read as base64 code, then it can be shown as an image..
My question is: how to parse these binary string into base64 code?
These looks like numbers in base 2. If that is the case you could take the first 6 bits of each number, for example "010010" out of the first set ("01001000") and get the decimal value for these 6 bits. In the case of the first number you'll get 18 base 10:
base10 = parseInt("010010", 2) -> 18
The next step would be to get the base64 for that decimal number. According to this table http://en.wikipedia.org/wiki/Base64 18 would be mapped to "S"
Then you take the next set of 6 bits which would be the remaining 2 from the first set of 8 ("00") plus 4 bits from the next segment ("0011") and perform the same operation:
base10 = parseInt("000011", 2) -> 3
Again, decimal 3 maps to "D" according to the Wikipedia link.
And you'll keep going until you process all the bits.
This page has bit of information on how to convert numbers in base 2 to base 10: http://www.name-generators.com/javascript-2/how-to-make-binary-decimal-conversion-in-javascript.htm
I tried my best to parse it and got a tarball... only one step to my destination but..
My solution in LiveScript, hope it helps...
require! \fs
require! \buffer
require! \path
require! \zlib
{exec} = require \child_process
show = console.log
fs.read-file \string.txt \utf8 (err, file) ->
# throw err if err?
res = file
.replace /\_/g, '1'
.replace /\n/g, ' '
.split ' '
.map -> parse-int it, 2
.map -> String.from-char-code it
.join ''
b = new Buffer res, \base64
zlib.gunzip b, (err, data) ->
fs.write-file \c.tar data
When I switch to Russian layout in Windows 7 and press ; key on the keyboard, I get Russian letter ж on the screen.
I am working on a application where I need to detected pressed keys and draw text on the screen. The requirement is handle all supported languages. This is my code:
// I scan the keyboard for pressed keys
for (short key = KEY_SCAN_MIN; key <= KEY_SCAN_MAX; ++key)
{
if (GetAsyncKeyState(key) & 0x8000)
{
// When I detect a pressed key, I convert the scan code into virtual key.
// The hkl is current keyboard layout parameter, which is Russian.
UINT virtualKey = MapVirtualKeyEx((UINT)key, MAPVK_VK_TO_CHAR, hkl);
// Next I get the state of the keyboard and convert the virtual key
// into Unicode letter
if (!GetKeyboardState(kbrdState))
{
continue;
}
// unicode is defined as wchar_t unicode[2];
int result = ToUnicodeEx(virtualKey, key, (BYTE*)kbrdState, unicode, 2, 0, hkl);
Everything works great except a couple letters in Russian and I cannot figure out why. One specific letter that does not work is ж. When I attempt to translate its scan code, the translation is б, which is a different Russian letter.
I have spent entire day debugging this issue and do not get too far. When I press this Russian key I get 168 for scan code and 1078 for the virtual key. I did this small test to convert the letter back to the virtual key.
short test = VkKeyScanEx(L'ж', hkl);
The value of variable test is 1078! I do not understand why converting letter ж to virtual key gives me 1078 but converting 1078 virtual key (using the same keyboard layout) gives me б.
I always use WM_CHAR to read scan codes as it does the translation work for you and returns the final character in UTF-16. Works with all languages, even ones with which it takes more than one key press to represent a single character.