/// expand # unicode escapes in a string. // @param text ASCII text with #XXXX, where XXXX is four hex digits. ## means # itself. // @return text as UTF-8 // @see testu.lua // @function utf8_expand def utf8_expand(Str text) { int len = strlen(text), i = 0, enc = get_encoding(); WCHAR wch; LPWSTR P = wbuff; if (len > sizeof(wbuff)) { return push_error_msg(L,"string too big"); } while (i <= len) { if (text[i] == '#') { ++i; if (text[i] == '#') { wch = '#'; } else if (len-i >= 4) { char hexnum[5]; strncpy(hexnum,text+i,4); hexnum[4] = '\0'; wch = strtol(hexnum,NULL,16); i += 3; } else { return push_error_msg(L,"bad # escape"); } } else { wch = (WCHAR)text[i]; } *P++ = wch; ++i; } *P++ = 0; set_encoding(CP_UTF8); push_wstring(L,wbuff); set_encoding(enc); return 1; }
/// send a string or virtual key to the active window. // @{input.lua} shows launching a process, waiting for it to be // ready, and sending it some keys // @param text either a key (like winapi.VK_SHIFT) or a string // @return number of keys sent, or nil if an error // @return any error string // @function send_to_window def send_to_window () { const char *text; int vkey, len = MAX_KEYS; UINT res; SHORT last_vk = 0; INPUT *input, *pi; if (lua_isnumber(L,1)) { INPUT inp; ZeroMemory(&inp,sizeof(INPUT)); vkey = lua_tointeger(L,1); add_input(&inp,vkey,lua_toboolean(L,2)); SendInput(1,&inp,sizeof(INPUT)); return 0; } else { text = lua_tostring(L,1); if (text == NULL) { return push_error_msg(L,"not a string or number"); } } input = (INPUT *)malloc(sizeof(INPUT)*len); pi = input; ZeroMemory(input, sizeof(INPUT)*len); for(; *text; ++text) { SHORT vk = VkKeyScan(*text); if (last_vk == vk) { pi = add_input(pi,last_vk & 0xFF,TRUE); } if (vk & 0x100) pi = add_input(pi,VK_SHIFT,FALSE); pi = add_input(pi,vk & 0xFF,FALSE); if (vk & 0x100) pi = add_input(pi,VK_SHIFT,TRUE); last_vk = vk; } res = SendInput(((DWORD_PTR)pi-(DWORD_PTR)input)/sizeof(INPUT), input, sizeof(INPUT)); free(input); if (res > 0) { lua_pushinteger(L,res); return 1; } else { return push_error(L); } return 0; }
/// wait for a group of processes. // @{process-wait.lua} shows a number of processes launched // in parallel // @param processes an array of @{Process} objects // @param all wait for all processes to finish (default false) // @param timeout wait upto this time in msec (default infinite) // @function wait_for_processes def wait_for_processes(Value processes, Boolean all, Int timeout = 0) { int status, i; Process *p; int n = lua_objlen(L,processes); HANDLE handles[MAXIMUM_WAIT_OBJECTS]; if (n > MAXIMUM_WAIT_OBJECTS) { return push_error_msg(L,"cannot wait on so many processes"); } for (i = 0; i < n; i++) { lua_rawgeti(L,processes,i+1); p = Process_arg(L,-1); handles[i] = p->hProcess; } status = WaitForMultipleObjects(n, handles, all, TIMEOUT(timeout)); status -= WAIT_OBJECT_0 + 1; if (status < 1 || status > n) { return push_error(L); } else { lua_pushinteger(L,status); return 1; } }
/// push a particular Windows error. // @param L the state // @param err the error code // @return 2; 'nil' and the message // @function push_error int push_error_code(lua_State *L, int err) { return push_error_msg(L,last_error(err)); }
/// push the last Windows error. // @param L the state // @return 2; 'nil' and the message // @function push_error int push_error(lua_State *L) { return push_error_msg(L,last_error(0)); }