Merge pull request #103 from go-vgo/dep-pr

add utf-8 support
This commit is contained in:
vz 2018-01-16 18:48:45 +08:00 committed by GitHub
commit 30660e6833
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 108 additions and 33 deletions

View File

@ -314,7 +314,7 @@ char* key_toggle(char *k, char *d, char *akey, char *keyT){
} }
void type_string(char *str){ void type_string(char *str){
typeString(str); typeStringDelayed(str, 0);
} }
void type_string_delayed(char *str, size_t cpm){ void type_string_delayed(char *str, size_t cpm){

View File

@ -68,14 +68,18 @@ void tapKey(char c, MMKeyFlags flags);
/* Sends a UTF-8 string without modifiers. */ /* Sends a UTF-8 string without modifiers. */
void typeString(const char *str); void typeString(const char *str);
/* Sends a Unicode character without modifiers. */
void unicodeType(const unsigned value);
/* Macro to convert WPM to CPM integers. /* Macro to convert WPM to CPM integers.
* (the average English word length is 5.1 characters.) */ * (the average English word length is 5.1 characters.) */
#define WPM_TO_CPM(WPM) (unsigned)(5.1 * WPM) #define WPM_TO_CPM(WPM) (unsigned)(5.1 * WPM)
/* Sends a string with partially random delays between each letter. Note that /* Sends UTF-8 string without modifiers and
* deadbeef_srand() must be called before this function if you actually want * with partially random delays between each letter.
* randomness. */ * Note that deadbeef_srand() must be called before this function
* if you actually want randomness.
* */
void typeStringDelayed(const char *str, const unsigned cpm); void typeStringDelayed(const char *str, const unsigned cpm);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -127,9 +127,8 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags)
assert(keyEvent != NULL); assert(keyEvent != NULL);
CGEventSetType(keyEvent, down ? kCGEventKeyDown : kCGEventKeyUp); CGEventSetType(keyEvent, down ? kCGEventKeyDown : kCGEventKeyUp);
// CGEventSetFlags(keyEvent, flags);
CGEventSetFlags(keyEvent, (int) flags); CGEventSetFlags(keyEvent, (int) flags);
// CGEventSetFlags(keyEvent, 0);
// CGEventSetFlags(keyEvent, kCGEventFlagMaskShift | kCGEventFlagMaskCommand);
CGEventPost(kCGSessionEventTap, keyEvent); CGEventPost(kCGSessionEventTap, keyEvent);
CFRelease(keyEvent); CFRelease(keyEvent);
} }
@ -193,15 +192,13 @@ void tapKey(char c, MMKeyFlags flags)
} }
#if defined(IS_MACOSX) #if defined(IS_MACOSX)
void toggleUniKey(char c, const bool down) void toggleUnicode(UniChar ch, const bool down)
{ {
/* This function relies on the convenient /* This function relies on the convenient
* CGEventKeyboardSetUnicodeString(), which allows us to not have to * CGEventKeyboardSetUnicodeString(), which allows us to not have to
* convert characters to a keycode, but does not support adding modifier * convert characters to a keycode, but does not support adding modifier
* flags. It is therefore only used in typeString() and typeStringDelayed() * flags. It is therefore only used in typeStringDelayed()
* -- if you need modifier keys, use the above functions instead. */ * -- if you need modifier keys, use the above functions instead. */
UniChar ch = (UniChar)c; /* Convert to unsigned char */
CGEventRef keyEvent = CGEventCreateKeyboardEvent(NULL, 0, down); CGEventRef keyEvent = CGEventCreateKeyboardEvent(NULL, 0, down);
if (keyEvent == NULL) { if (keyEvent == NULL) {
fputs("Could not create keyboard event.\n", stderr); fputs("Could not create keyboard event.\n", stderr);
@ -213,33 +210,80 @@ void toggleUniKey(char c, const bool down)
CGEventPost(kCGSessionEventTap, keyEvent); CGEventPost(kCGSessionEventTap, keyEvent);
CFRelease(keyEvent); CFRelease(keyEvent);
} }
#else #endif
#if defined(USE_X11)
#define toggleUniKey(c, down) toggleKey(c, down, MOD_NONE) #define toggleUniKey(c, down) toggleKey(c, down, MOD_NONE)
#endif #endif
static void tapUniKey(char c) // unicode type
{ void unicodeType(const unsigned value){
toggleUniKey(c, true); #if defined(IS_MACOSX)
toggleUniKey(c, false); UniChar ch = (UniChar)value; // Convert to unsigned char
toggleUnicode(ch, true);
toggleUnicode(ch, false);
#elif defined(IS_WINDOWS)
INPUT ip;
// Set up a generic keyboard event.
ip.type = INPUT_KEYBOARD;
ip.ki.wVk = 0; // Virtual-key code
ip.ki.wScan = value; // Hardware scan code for key
ip.ki.time = 0; // System will provide its own time stamp.
ip.ki.dwExtraInfo = 0; // No extra info. Use the GetMessageExtraInfo function to obtain this information if needed.
ip.ki.dwFlags = KEYEVENTF_UNICODE; // KEYEVENTF_KEYUP for key release.
SendInput(1, &ip, sizeof(INPUT));
#elif defined(USE_X11)
toggleUniKey(value, true);
toggleUniKey(value, false);
#endif
} }
void typeString(const char *str) void typeStringDelayed(const char *str, const unsigned cpm){
{
while (*str != '\0') {
tapUniKey(*str++);
}
}
void typeStringDelayed(const char *str, const unsigned cpm)
{
/* Characters per second */ /* Characters per second */
const double cps = (double)cpm / 60.0; const double cps = (double)cpm / 60.0;
/* Average milli-seconds per character */ /* Average milli-seconds per character */
const double mspc = (cps == 0.0) ? 0.0 : 1000.0 / cps; const double mspc = (cps == 0.0) ? 0.0 : 1000.0 / cps;
unsigned long n;
unsigned short c;
unsigned short c1;
unsigned short c2;
unsigned short c3;
while (*str != '\0') { while (*str != '\0') {
tapUniKey(*str++); c = *str++;
microsleep(mspc + (DEADBEEF_UNIFORM(0.0, 62.5)));
// warning, the following utf8 decoder
// doesn't perform validation
if (c <= 0x7F) {
// 0xxxxxxx one byte
n = c;
} else if ((c & 0xE0) == 0xC0) {
// 110xxxxx two bytes
c1 = (*str++) & 0x3F;
n = ((c & 0x1F) << 6) | c1;
} else if ((c & 0xF0) == 0xE0) {
// 1110xxxx three bytes
c1 = (*str++) & 0x3F;
c2 = (*str++) & 0x3F;
n = ((c & 0x0F) << 12) | (c1 << 6) | c2;
} else if ((c & 0xF8) == 0xF0) {
// 11110xxx four bytes
c1 = (*str++) & 0x3F;
c2 = (*str++) & 0x3F;
c3 = (*str++) & 0x3F;
n = ((c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
}
unicodeType(n);
if (mspc > 0) {
microsleep(mspc + (DEADBEEF_UNIFORM(0.0, 62.5)));
}
} }
} }

View File

@ -670,6 +670,33 @@ func WriteAll(text string) {
clipboard.WriteAll(text) clipboard.WriteAll(text)
} }
// CharCodeAt char code at utf-8
func CharCodeAt(s string, n int) rune {
i := 0
for _, r := range s {
if i == n {
return r
}
i++
}
return 0
}
// TypeStr type string, support UTF-8
func TypeStr(str string) {
for i := 0; i < len([]rune(str)); i++ {
ustr := uint32(CharCodeAt(str, i))
UnicodeType(ustr)
}
}
// UnicodeType unicode tap uint32
func UnicodeType(str uint32) {
cstr := C.uint(str)
C.unicodeType(cstr)
}
// TypeString type string // TypeString type string
func TypeString(x string) { func TypeString(x string) {
cx := C.CString(x) cx := C.CString(x)
@ -677,8 +704,8 @@ func TypeString(x string) {
defer C.free(unsafe.Pointer(cx)) defer C.free(unsafe.Pointer(cx))
} }
// TypeStr type string, support UTF-8 // TypeStrP paste string, support UTF-8
func TypeStr(str string) { func TypeStrP(str string) {
clipboard.WriteAll(str) clipboard.WriteAll(str)
if runtime.GOOS == "darwin" { if runtime.GOOS == "darwin" {
KeyTap("v", "command") KeyTap("v", "command")
@ -688,11 +715,11 @@ func TypeStr(str string) {
} }
// TypeStrDelay type string delayed // TypeStrDelay type string delayed
func TypeStrDelay(x string, y int) { func TypeStrDelay(str string, y int) {
cx := C.CString(x) cstr := C.CString(str)
cy := C.size_t(y) cy := C.size_t(y)
C.type_string_delayed(cx, cy) C.type_string_delayed(cstr, cy)
defer C.free(unsafe.Pointer(cx)) defer C.free(unsafe.Pointer(cstr))
} }
// TypeStringDelayed type string delayed, Wno-deprecated // TypeStringDelayed type string delayed, Wno-deprecated