size_t regerror(int errcode, const regex_t *preg, MCStringRef &errbuf) { const char *message, *addmessage; size_t length, addlength; message = (errcode >= (int)(sizeof(pstring)/sizeof(char *))) ? "unknown error code" : pstring[errcode]; length = strlen(message) + 1; addmessage = " at offset "; addlength = (preg != NULL && (int)preg->re_erroffset != -1) ? strlen(addmessage) + 6 : 0; if (addlength > 0) { MCAutoStringRef t_error_string; MCStringFormat(&t_error_string, "%s%s%-6d", message, addmessage, (int)preg->re_erroffset); MCValueAssign(errbuf, *t_error_string); } else { if (errbuf != nil) MCValueRelease(errbuf); /* UNCHECKED */ MCStringCreateWithNativeChars((const char_t *) message, strlen(message), errbuf); } return length + addlength; }
static void getfilter(MCStringRef p_filter, MCStringRef &r_filter) { if (p_filter != nil && !MCStringIsEmpty(p_filter)) { static MCAutoStringRef t_filterstring; if (*t_filterstring != nil) MCValueRelease(*t_filterstring); /* UNCHECKED */ MCStringMutableCopy(p_filter, &t_filterstring); uindex_t t_offset; if (!MCStringFirstIndexOfChar(*t_filterstring, '\n', 0, kMCStringOptionCompareExact, t_offset) && !MCStringFirstIndexOfChar(*t_filterstring, ',', 0, kMCStringOptionCompareExact, t_offset)) { MCStringAppendChar(*t_filterstring, '\0'); MCStringAppend(*t_filterstring, p_filter); } /* UNCHECKED */ MCStringAppendChar(*t_filterstring, '\0'); /* UNCHECKED */ MCStringFindAndReplaceChar(*t_filterstring, '\n', '\0', kMCStringOptionCompareExact); /* UNCHECKED */ MCStringFindAndReplaceChar(*t_filterstring, ',', '\0', kMCStringOptionCompareExact); MCStringCopy(*t_filterstring, r_filter); } else /* UNCHECKED */ MCStringCreateWithNativeChars((const char_t *)"All Files (*.*)\0*.*\0", 20, r_filter); }
MCParagraph *MCCdata::getparagraphs() { MCParagraph *paragraphs; if (id & COMPACT_PARAGRAPHS) { paragraphs = NULL; char *eptr = (char *)data; while ((eptr = strtok(eptr, "\n")) != NULL) { MCParagraph *tpgptr = new (nothrow) MCParagraph; tpgptr->appendto(paragraphs); uint2 l = strlen(eptr) + 1; /* UNCHECKED */ MCAutoPointer<char_t[]> sptr = new (nothrow) char_t[l]; memcpy(sptr.Get(), eptr, l); MCAutoStringRef t_string; /* UNCHECKED */ MCStringCreateWithNativeChars(sptr.Get(), l, &t_string); tpgptr->settext(*t_string); eptr = NULL; } delete (char *)data; data = paragraphs; id &= ~COMPACT_PARAGRAPHS; } if (data == NULL) data = paragraphs = new (nothrow) MCParagraph; else paragraphs = (MCParagraph *)data; return paragraphs; }
void MCPlatformHandleKeyUp(MCPlatformWindowRef p_window, MCPlatformKeyCode p_key_code, codepoint_t p_mapped_codepoint, codepoint_t p_unmapped_codepoint) { // SN-2014-10-31: [[ Bug 13832 ]] We now output all the key messages that have been queued // (by either MCPlatformHandleKeyDown, or MCPlatformHandleTextInputInsertText) while (s_pending_key_up != nil) { MCPlatformKeyCode t_mapped_key_code; MCAutoStringRef t_mapped_char; // SN-2015-06-23: [[ Bug 3537 ]] We don't want to map a nativised char - // but we want to map key strokes like F1 and such // This is intended to mimic the behaviour of the key down process, // in which MCDispatcher::wkdown is called with the nativised char if (s_pending_key_up -> needs_mapping) map_key_to_engine(s_pending_key_up -> key_code, s_pending_key_up -> mapped_codepoint, s_pending_key_up -> unmapped_codepoint, t_mapped_key_code, &t_mapped_char); else { /* UNCHECKED */ MCStringCreateWithNativeChars((const char_t*)&(s_pending_key_up -> mapped_codepoint), 1, &t_mapped_char); t_mapped_key_code = s_pending_key_up -> key_code; } MCdispatcher -> wkup(p_window, *t_mapped_char, t_mapped_key_code); MCKeyMessageNext(s_pending_key_up); } }
static void synthesize_key_press(MCPlatformWindowRef p_window, char p_char, KeySym p_sym) { MCAutoStringRef t_key; /* UNCHECKED */ MCStringCreateWithNativeChars((char_t*)&p_char, 1, &t_key); MCdispatcher -> wkdown(p_window, *t_key, p_sym); MCdispatcher -> wkup(p_window, *t_key, p_sym); }
static void get_new_filter(MCStringRef *p_types, uint4 p_type_count, MCStringRef &r_filters) { MCAutoStringRef t_filters; /* UNCHECKED */ MCStringCreateMutable(0, &t_filters); for(uint4 t_type_index = 0; t_type_index < p_type_count; ++t_type_index) { MCAutoStringRefArray t_split; /* UNCHECKED */ MCStringsSplit(p_types[t_type_index], '|', t_split.PtrRef(), t_split.CountRef()); if (t_split.Count() < 1 || (t_split.Count() == 1 && MCStringIsEmpty(t_split[0]))) continue; if (t_type_index != 0) /* UNCHECKED */ MCStringAppendChar(*t_filters, '\0'); /* UNCHECKED */ MCStringAppend(*t_filters, t_split[0]); if (t_split.Count() < 2) /* UNCHECKED */ MCStringAppendChars(*t_filters, L"\0*.*", 4); else { MCAutoStringRefArray t_extensions; /* UNCHECKED */ MCStringsSplit(t_split[1], ',', t_extensions.PtrRef(), t_extensions.CountRef()); // SN-2014-07-28: [[ Bug 12972 ]] Filters "Tag|" should be understood as "Tag" // and allow all the file types if (t_extensions.Count() == 0 || (t_extensions.Count() == 1 && MCStringIsEmpty(t_extensions[0]))) /* UNCHECKED */ MCStringAppendChars(*t_filters, L"\0*.*", 4); else { for (unsigned int i = 0; i < t_extensions.Count(); ++i) { if (i != 0) /* UNCHECKED*/ MCStringAppendChar(*t_filters, ';'); else /* UNCHECKED*/ MCStringAppendChar(*t_filters, '\0'); /* UNCHECKED */ MCStringAppendFormat(*t_filters, "*.%@", t_extensions[i]); } } } } if (MCStringIsEmpty(*t_filters)) /* UNCHECKED */ MCStringCreateWithNativeChars((char_t*)"All Files\0*.*\0\0", 15, r_filters); else { /* UNCHECKED */ MCStringAppendChar(*t_filters, '\0'); MCStringCopy(*t_filters, r_filters); } }
// 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; }
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(); }