add utf-8 support

This commit is contained in:
vcaesar 2018-01-16 18:01:19 +08:00
parent 8733401ce5
commit 5005c38b4f
4 changed files with 102 additions and 34 deletions

View File

@ -314,7 +314,7 @@ char* key_toggle(char *k, char *d, char *akey, char *keyT){
}
void type_string(char *str){
typeString(str);
typeStringDelayed(str, 0);
}
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. */
void typeString(const char *str);
/* Sends a Unicode character without modifiers. */
void unicodeType(const unsigned value);
/* Macro to convert WPM to CPM integers.
* (the average English word length is 5.1 characters.) */
#define WPM_TO_CPM(WPM) (unsigned)(5.1 * WPM)
/* Sends a string with partially random delays between each letter. Note that
* deadbeef_srand() must be called before this function if you actually want
* randomness. */
/* Sends UTF-8 string without modifiers and
* with partially random delays between each letter.
* Note that deadbeef_srand() must be called before this function
* if you actually want randomness.
* */
void typeStringDelayed(const char *str, const unsigned cpm);
#ifdef __cplusplus

View File

@ -127,9 +127,8 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags)
assert(keyEvent != NULL);
CGEventSetType(keyEvent, down ? kCGEventKeyDown : kCGEventKeyUp);
// CGEventSetFlags(keyEvent, flags);
CGEventSetFlags(keyEvent, (int) flags);
// CGEventSetFlags(keyEvent, 0);
// CGEventSetFlags(keyEvent, kCGEventFlagMaskShift | kCGEventFlagMaskCommand);
CGEventPost(kCGSessionEventTap, keyEvent);
CFRelease(keyEvent);
}
@ -193,15 +192,13 @@ void tapKey(char c, MMKeyFlags flags)
}
#if defined(IS_MACOSX)
void toggleUniKey(char c, const bool down)
void toggleUnicode(UniChar ch, const bool down)
{
/* This function relies on the convenient
* CGEventKeyboardSetUnicodeString(), which allows us to not have to
* 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. */
UniChar ch = (UniChar)c; /* Convert to unsigned char */
CGEventRef keyEvent = CGEventCreateKeyboardEvent(NULL, 0, down);
if (keyEvent == NULL) {
fputs("Could not create keyboard event.\n", stderr);
@ -213,33 +210,73 @@ void toggleUniKey(char c, const bool down)
CGEventPost(kCGSessionEventTap, keyEvent);
CFRelease(keyEvent);
}
#else
#define toggleUniKey(c, down) toggleKey(c, down, MOD_NONE)
#endif
static void tapUniKey(char c)
{
toggleUniKey(c, true);
toggleUniKey(c, false);
// unicode type
void unicodeType(const unsigned value){
#if defined(IS_MACOSX)
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));
#endif
}
void typeString(const char *str)
{
while (*str != '\0') {
tapUniKey(*str++);
}
}
void typeStringDelayed(const char *str, const unsigned cpm)
{
void typeStringDelayed(const char *str, const unsigned cpm){
/* Characters per second */
const double cps = (double)cpm / 60.0;
/* Average milli-seconds per character */
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') {
tapUniKey(*str++);
microsleep(mspc + (DEADBEEF_UNIFORM(0.0, 62.5)));
c = *str++;
// 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)
}
// 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
func TypeString(x string) {
cx := C.CString(x)
@ -677,8 +704,8 @@ func TypeString(x string) {
defer C.free(unsafe.Pointer(cx))
}
// TypeStr type string, support UTF-8
func TypeStr(str string) {
// TypeStrP paste string, support UTF-8
func TypeStrP(str string) {
clipboard.WriteAll(str)
if runtime.GOOS == "darwin" {
KeyTap("v", "command")
@ -688,11 +715,11 @@ func TypeStr(str string) {
}
// TypeStrDelay type string delayed
func TypeStrDelay(x string, y int) {
cx := C.CString(x)
func TypeStrDelay(str string, y int) {
cstr := C.CString(str)
cy := C.size_t(y)
C.type_string_delayed(cx, cy)
defer C.free(unsafe.Pointer(cx))
C.type_string_delayed(cstr, cy)
defer C.free(unsafe.Pointer(cstr))
}
// TypeStringDelayed type string delayed, Wno-deprecated