static void build_paths(MCStringRef &r_path) { MCAutoStringRef t_path; /* UNCHECKED */ MCStringCreateMutable(0, &t_path); MCAutoStringRef t_std_path; MCAutoStringRef t_native_path; /* UNCHECKED */ MCStringCreateWithChars(s_chosen_folder.Ptr(), s_chosen_folder.Size()-1, &t_native_path); /* UNCHECKED */ MCS_pathfromnative(*t_native_path, &t_std_path); if (MCStringGetCharAtIndex(*t_std_path, 0) == '"') { // Does this ever actually receive a quoted path? /*Meta::itemised_string t_items(sg_chosen_files, ' ', true); for(unsigned int t_index = 0; t_index < t_items . count(); ++t_index) { if (t_index != 0) /* UNCHECKED * / MCStringAppendChar(*t_path, '\n'); build_path(*t_std_path, t_items[t_index], *t_path); }*/ MCAutoStringRef t_item; /* UNCHECKED */ MCStringCreateWithChars(s_chosen_files.Ptr(), s_chosen_files.Size()-1, &t_item); build_path(*t_std_path, *t_item, *t_path); } else { MCAutoStringRef t_files; /* UNCHECKED */ MCStringCreateWithChars(s_chosen_files.Ptr(), s_chosen_files.Size()-1, &t_files); build_path(*t_std_path, *t_files, *t_path); } s_chosen_files.Delete(); s_chosen_folder.Delete(); MCStringCopy(*t_path, r_path); }
static MCStringRef windows_query_locale(uint4 t_index) { // Allocate a buffer for the locale information int t_buf_size; t_buf_size = GetLocaleInfoW(LOCALE_USER_DEFAULT, t_index, NULL, 0); wchar_t* t_buffer = new wchar_t[t_buf_size]; // Get the locale information and create a StringRef from it if (GetLocaleInfoW(LOCALE_USER_DEFAULT, t_index, t_buffer, t_buf_size) == 0) return MCValueRetain(kMCEmptyString); MCStringRef t_string; MCStringCreateWithChars(t_buffer, MCU_max(0, t_buf_size - 1), t_string); delete[] t_buffer; return t_string; }
static HRESULT append_shellitem_path_and_release(IShellItem *p_item, bool p_first, MCStringRef &x_string) { HRESULT t_hresult; t_hresult = S_OK; bool t_succeeded; t_succeeded = true; WCHAR *t_filename; t_filename = NULL; if (t_succeeded) { t_hresult = p_item -> GetDisplayName(SIGDN_FILESYSPATH, &t_filename); t_succeeded = SUCCEEDED(t_hresult); } if (t_succeeded) { if (x_string == nil) MCStringCreateMutable(0, x_string); else if (!MCStringIsMutable(x_string)) { MCStringRef t_clone; MCStringMutableCopy(x_string, t_clone); MCValueAssign(x_string, t_clone); } MCAutoStringRef t_rev_filename; MCAutoStringRef t_native_filename; /* UNCHECKED */ MCStringCreateWithChars(t_filename, lstrlenW(t_filename), &t_native_filename); /* UNCHECKED */ MCS_pathfromnative(*t_native_filename, &t_rev_filename); /* UNCHECKED */ MCStringAppendFormat(x_string, p_first ? "%@" : "\n%@", *t_rev_filename); } if (t_filename != NULL) CoTaskMemFree(t_filename); if (p_item != NULL) p_item -> Release(); return t_hresult; }
// MW-2014-06-25: [[ Bug 12370 ]] Map an input keyCode and mapped codepoint to // engine keysym and char. The engine expects keyCode to be the mapped key // if an ascii character and the raw keycode if not. static void map_key_to_engine(MCPlatformKeyCode p_key_code, codepoint_t p_mapped_codepoint, codepoint_t p_unmapped_codepoint, MCPlatformKeyCode& r_key_code, MCStringRef &r_native_char) { if (p_mapped_codepoint <= 0xffff) { uint16_t t_unicode_char; char_t t_native_char; // MW-2014-08-05: [[ Bug 13042 ]] This was a mis-merge from an updated fix to bug 12747 // (the code previously was using unmapped codepoint). t_unicode_char = p_mapped_codepoint & 0xffff; if (MCUnicodeMapToNative(&t_unicode_char, 1, t_native_char)) { /* UNCHECKED */ MCStringCreateWithNativeChars(&t_native_char, 1, r_native_char); // MW-2014-06-25: [[ Bug 12370 ]] The engine expects keyCode to be the mapped key whenever // the mapped key is ASCII. If the mapped key is not ASCII then the keyCode reflects // the raw (US English) keycode. // SN-2014-12-08: [[ Bug 14067 ]] Avoid to use the native char instead of the key code // the numeric keypad keys. if (isascii(t_native_char) && (p_key_code < kMCPlatformKeyCodeKeypadSpace || p_key_code > kMCPlatformKeyCodeKeypadEqual)) r_key_code = t_native_char; else r_key_code = p_key_code; return; } // SN-2014-12-05: [[ Bug 14162 ]] We can have unicode chars being typed. // We keep the given keycode (the codepoint) as the key code in these conditions. else { /* UNCHECKED */ MCStringCreateWithChars(&t_unicode_char, 1, r_native_char); r_key_code = p_key_code; return; } } r_native_char = MCValueRetain(kMCEmptyString); r_key_code = p_key_code; }
// MW-2005-05-15: Updated for new answer command restructuring int MCA_folder(MCStringRef p_title, MCStringRef p_prompt, MCStringRef p_initial, unsigned int p_options, MCStringRef &r_value, MCStringRef &r_result) { if (MCmajorosversion >= 0x0600 && MCModeMakeLocalWindows()) return MCA_file(p_title, p_prompt, nil, p_initial, p_options | MCA_OPTION_FOLDER_DIALOG, r_value, r_result); // MW-2005-05-27: We'll use a static (I know bad me) to store the version // of the shell dll. static int s_shell_version = -1; static MCStringRef s_last_folder = MCValueRetain(kMCEmptyString); MCAutoStringRef t_native_filename; if (p_initial != NULL) { MCAutoStringRef t_std_path; /* UNCHECKED */ MCS_pathfromnative(p_initial, &t_std_path); t_native_filename = *t_std_path; } else t_native_filename = MCValueRetain(s_last_folder); if (!MCModeMakeLocalWindows()) { MCAutoStringRef t_answer_path; MCRemoteFolderDialog(p_title, p_prompt, *t_native_filename, &t_answer_path); if (*t_answer_path != nil) { MCAutoStringRef t_std_path; /* UNCHECKED */ MCS_pathfromnative(*t_answer_path, &t_std_path); MCValueAssign(s_last_folder, *t_std_path); } r_value = MCValueRetain(*t_answer_path); return 0; } if (s_shell_version == -1) s_shell_version = get_dll_version(L"shell32.dll"); bool sheet = (p_options & MCA_OPTION_SHEET) != 0; BROWSEINFOW bi; memset(&bi, 0, sizeof(BROWSEINFOW)); Window pw; pw = MCModeGetParentWindow(); if (pw != DNULL) bi.hwndOwner = (HWND)pw->handle.window; MCAutoStringRefAsWString t_prompt_wstr; MCAutoStringRefAsWString t_native_filename_wstr; /* UNCHECKED */ t_prompt_wstr.Lock(p_prompt); bi.pidlRoot = NULL; bi.lpszTitle = *t_prompt_wstr; bi.ulFlags = BIF_RETURNONLYFSDIRS; if (s_shell_version >= 500) bi.ulFlags |= BIF_NEWDIALOGSTYLE; if (*t_native_filename != nil && !MCStringIsEmpty(*t_native_filename)) { t_native_filename_wstr.Lock(*t_native_filename); bi . lpfn = BrowseCallbackProc; bi . lParam = (LPARAM)*t_native_filename_wstr; } else { bi.lpfn = NULL; bi.lParam = NULL; } LPITEMIDLIST lpiil; LPMALLOC lpm; SHGetMalloc(&lpm); DWORD t_error; lpiil = SHBrowseForFolderW(&bi); if (lpiil == NULL) { t_error = GetLastError(); } MCAutoArray<unichar_t> t_buffer; /* UNCHECKED */ t_buffer.New(MAX_PATH); if (lpiil != NULL && SHGetPathFromIDListW(lpiil, t_buffer.Ptr())) { if (s_last_folder != NULL) MCValueRelease(s_last_folder); size_t t_length; /* UNCHECKED */ StringCchLength(t_buffer.Ptr(), t_buffer.Size(), &t_length); /* UNCHECKED */ MCStringCreateWithChars(t_buffer.Ptr(), t_length, s_last_folder); MCAutoStringRef t_std_path; /* UNCHECKED */ MCS_pathfromnative(s_last_folder, &t_std_path); r_value = MCValueRetain(*t_std_path); } else r_result = MCSTR(MCcancelstring); // SMR 1880 clear shift and button state waitonbutton(); lpm->Free(lpiil); lpm->Release(); return 0; }
void MCPlatformHandleTextInputInsertText(MCPlatformWindowRef p_window, unichar_t *p_chars, uindex_t p_char_count, MCRange p_replace_range, MCRange p_selection_range, bool p_mark) { if (!MCactivefield) return; // SN-2014-12-04: [[ Bug 14152 ]] Locking the screen here doesn't allow the screen to refresh after // text input, inside an MCWait loop // MCRedrawLockScreen(); int32_t t_r_si, t_r_ei; t_r_si = 0; t_r_ei = INT32_MAX; MCactivefield -> resolvechars(0, t_r_si, t_r_ei, p_replace_range . offset, p_replace_range . length); // SN-2014-09-15: [[ Bug 13423 ]] t_was_compositing now used further in the function bool t_was_compositing; t_was_compositing = false; if (!p_mark) { // MW-2014-08-05: [[ Bug 13098 ]] If we have been compositing, then don't synthesise a // keyDown / keyUp. int4 si, ei; if (MCactivefield -> getcompositionrange(si, ei)) { if (si < t_r_si) t_r_si -= MCMin(t_r_si - si, ei - si); if (si < t_r_ei) t_r_ei -= MCMin(t_r_ei - si, ei - si); MCactivefield -> stopcomposition(True, False); t_was_compositing = true; } else t_was_compositing = false; // If the char count is 1 and the replacement range matches the current selection, // the char is native and the requested selection is after the char, then synthesis a // keydown/up pair. // MW-2014-06-25: [[ Bug 12370 ]] If the char is ascii then map appropriately so we get // the keycodes the engine expects. char_t t_char; if (!t_was_compositing && p_char_count == 1 && MCUnicodeMapToNative(p_chars, 1, t_char) && p_selection_range . offset == p_replace_range . offset + 1 && p_selection_range . length == 0) { int32_t t_s_si, t_s_ei; MCactivefield -> selectedmark(False, t_s_si, t_s_ei, False); if (t_s_si == t_r_si && t_s_ei == t_r_ei) { // SN-2014-09-15: [[ Bug 13423 ]] Send the messages for all the characters typed while (s_pending_key_down != nil) { // MW-2014-04-15: [[ Bug 12086 ]] Pass the keycode from the last event that was // passed to the IME. MCAutoStringRef t_mapped_char; MCPlatformKeyCode t_mapped_key_code; map_key_to_engine(s_pending_key_down -> key_code, s_pending_key_down -> mapped_codepoint, s_pending_key_down -> unmapped_codepoint, t_mapped_key_code, &t_mapped_char); // SN-2014-11-03: [[ Bug 13832 ]] Enqueue the event, instead of firing it now (we are still in the NSApplication's keyDown). // PM-2015-05-15: [[ Bug 15372]] call MCKeyMessageAppend before wkdown to prevent a crash if 'wait with messages' is used (since s_pending_key_down might become nil after wkdown MCKeyMessageAppend(s_pending_key_up, s_pending_key_down -> key_code, s_pending_key_down -> mapped_codepoint, s_pending_key_down -> unmapped_codepoint); MCdispatcher -> wkdown(p_window, *t_mapped_char, t_mapped_key_code); MCKeyMessageNext(s_pending_key_down); } return; } } } else { if (p_char_count == 0) MCactivefield -> stopcomposition(True, False); else { int4 si, ei; if (MCactivefield -> getcompositionrange(si, ei)) { if (si < t_r_si) t_r_si -= MCMin(t_r_si - si, ei - si); if (si < t_r_ei) t_r_ei -= MCMin(t_r_ei - si, ei - si); MCactivefield -> stopcomposition(True, False); } } } // SN-2014-09-14: [[ Bug 13423 ]] MCPlatformHandleRawKeyDown gets the US mac layout key, without any modifier included. // We need to update the elements: // if the key pressed leads to an actual char: // this wrong key is replaced by this new 'combined' char // if the key pressed fails to generate a char: // this wrong key is replaced by the dead-key char // SN-2015-04-10: [[ Bug 14205 ]] When using the dictation, there is no // pending key down, but the composition was still on though. // SN-2015-06-23: [[ Bug 3537 ]] We should not cast p_char as a uint1 if it // is not a native char. uint1 t_char[2]; bool t_is_native_char; t_is_native_char = MCUnicodeMapToNative(p_chars, 1, t_char[0]); t_char[1] = 0; if (t_was_compositing && s_pending_key_down && t_is_native_char) { s_pending_key_down -> key_code = (uint1)*t_char; s_pending_key_down -> mapped_codepoint = (uint1)*t_char; s_pending_key_down -> unmapped_codepoint = (uint1)*t_char; // SN-2015-05-18: [[ Bug 15385 ]] Enqueue the first char in the sequence // here - that will be the same as keyDown. // SN-2015-06-23: [[ Bug 3537 ]] In this only case, we don't want this // nativised char to be mapped again in MCPlatformHandleKeyUp. MCKeyMessageAppend(s_pending_key_up, (uint1)*t_char, (uint1)*t_char, (uint1)*t_char, false); } // Set the text. MCactivefield -> seltext(t_r_si, t_r_ei, False); if (p_mark) MCactivefield -> startcomposition(); // SN-2014-09-15: [[ Bug 13423 ]] If the character typed is not Unicode and follows a dead key character, then we send // [Raw]KeyDown/Up and remove the first character from the sequence of keys typed. // If the character successfully combined with the dead char before it in a native char, we don't use finsert // Otherwise, we have the dead char in p_chars, we need to remove the one stored first in the sequence MCAutoStringRef t_string; // SN-2015-01-20: [[ Bug 14406 ]] If we have a series of pending keys, we have two possibilities: // - typing IME characters: the characters are native, so we use the finsertnew // - typing dead characters: the character, if we arrive here, is > 127 // SN-2015-04-13: [[ Bug 14205 ]] Ensure that s_pending_key_down is not nil if (*p_chars > 127 && s_pending_key_down && s_pending_key_down -> next && t_is_native_char) { MCStringCreateWithNativeChars((const char_t *)t_char, 1, &t_string); MCdispatcher -> wkdown(p_window, *t_string, *t_char); MCKeyMessageNext(s_pending_key_down); } else { MCStringCreateWithChars(p_chars, p_char_count, &t_string); // SN-2014-12-05: [[ Bug 14162 ]] In case the character is a Unicode alphanumeric char, // then that's not a combining char - and it deserves its (raw)Key(Down|Up) messages uint32_t t_codepoint; t_codepoint = MCStringGetCodepointAtIndex(*t_string, 0); // SN-2015-05-18: [[ Bug 3537 ]] Use p_mark to determine whether we are // in an IME state // SN-2015-05-05: [[ Bug 15305 ]] Check that s_pending_key_down is not // nil before trying to use it, and use IME only if p_mark says so. if (s_pending_key_down && !p_mark) { MCAutoStringRef t_mapped_char; MCPlatformKeyCode t_mapped_key_code; map_key_to_engine(s_pending_key_down -> key_code, s_pending_key_down -> mapped_codepoint, s_pending_key_down -> unmapped_codepoint, t_mapped_key_code, &t_mapped_char); MCdispatcher -> wkdown(p_window, *t_string, *p_chars); // SN-2015-05-18: [[ Bug 3537 ]] If we were compositing, then we want // to send the same message for keyUp and keyDown - which might be // seeveral character-long if (t_was_compositing) MCdispatcher -> wkup(p_window, *t_string, *p_chars); else MCKeyMessageAppend(s_pending_key_up, *p_chars, s_pending_key_down -> mapped_codepoint, s_pending_key_down -> unmapped_codepoint); MCKeyMessageNext(s_pending_key_down); } else MCactivefield -> finsertnew(FT_IMEINSERT, *t_string, True); } // And update the selection range. int32_t t_s_si, t_s_ei; t_s_si = 0; t_s_ei = INT32_MAX; MCactivefield -> resolvechars(0, t_s_si, t_s_ei, p_selection_range . offset, p_selection_range . length); MCactivefield -> setcompositioncursoroffset(t_s_si - t_r_si); MCactivefield -> seltext(t_s_si, t_s_ei, True); // SN-2014-12-04: [[ Bug 14152 ]] Locking the screen here doesn't allow the screen to refresh after // text input, inside an MCWait loop // MCRedrawUnlockScreen(); }