// MW-2008-03-18: [[ Bug 3300 ]] Make sure that if a file has a full path we dont' prepend // the selected folder. // MW-2008-03-18: [[ Bug 6116 ]] Make sure that we don't add an extra slash if there's already // one at the end of the folder path. static void build_path(MCStringRef p_folder, MCStringRef p_file, MCStringRef x_path) { MCAutoStringRef t_path, t_engine_path; MCStringCreateMutable(0, &t_path); MCS_pathfromnative(p_file, &t_engine_path); // Check for absolute paths bool t_use_folder; if (MCStringIsEmpty(p_folder) || (MCStringGetLength(*t_engine_path) > 1 && MCStringGetCharAtIndex(*t_engine_path, 1) == ':') || (MCStringGetLength(*t_engine_path) > 2 && MCStringGetCharAtIndex(*t_engine_path, 0) == '/' && MCStringGetCharAtIndex(*t_engine_path, 1) == '/')) { t_use_folder = false; } else { t_use_folder = true; } if (t_use_folder) { // Add the folder and a separator, if required MCStringAppend(*t_path, p_folder); if (MCStringGetCharAtIndex(p_folder, MCStringGetLength(p_folder) - 1) != '/') MCStringAppendChar(*t_path, '/'); } MCStringAppend(*t_path, *t_engine_path); if (*t_path != nil) MCStringAppend(x_path, *t_path); }
void MCArraysExecCombine(MCExecContext& ctxt, MCArrayRef p_array, MCStringRef p_element_delimiter, MCStringRef p_key_delimiter, MCStringRef& r_string) { bool t_success; t_success = true; uindex_t t_count; t_count = MCArrayGetCount(p_array); MCAutoStringRef t_string; if (t_success) t_success = MCStringCreateMutable(0, &t_string); combine_array_t t_lisctxt; t_lisctxt . elements = nil; if (t_success) t_success = MCMemoryNewArray(t_count, t_lisctxt . elements); if (t_success) { t_lisctxt . index = 0; MCArrayApply(p_array, list_array_elements, &t_lisctxt); qsort(t_lisctxt . elements, t_count, sizeof(array_element_t), compare_array_element); for(uindex_t i = 0; i < t_count; i++) { MCAutoStringRef t_value_as_string; t_success = ctxt . ConvertToString(t_lisctxt . elements[i] . value, &t_value_as_string); if (!t_success) break; t_success = (p_key_delimiter == nil || (MCStringAppend(*t_string, MCNameGetString(t_lisctxt . elements[i] . key)) && MCStringAppend(*t_string, p_key_delimiter)))&& MCStringAppend(*t_string, *t_value_as_string) && (i == t_count - 1 || MCStringAppend(*t_string, p_element_delimiter)); if (!t_success) break; } } if (t_success) t_success = MCStringCopy(*t_string, r_string); MCMemoryDeleteArray(t_lisctxt . elements); if (t_success) return; // Throw the current error code (since last library call returned false). ctxt . Throw(); }
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); } }
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; }
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); }
void MCLicenseGetRevLicenseInfo(MCExecContext& ctxt, MCStringRef& r_info) { static const char *s_deploy_targets[] = { "Windows", "Mac OS X", "Linux", "iOS", "Android", "Windows Mobile", "Linux Mobile", "Server", "iOS Embedded", "Android Embedded", "HTML5", "FileMaker", }; bool t_success; MCAutoStringRef t_info; t_success = MCStringCreateMutable(0, &t_info); MCStringRef t_license_name; t_license_name = MClicenseparameters . license_name; if (t_license_name == nil) t_license_name = kMCEmptyString; MCStringRef t_license_org; t_license_org = MClicenseparameters . license_organization; if (t_license_org == nil) t_license_org = kMCEmptyString; MCAutoStringRef t_class; if (t_success) t_success = MCStringFromLicenseClass(MClicenseparameters . license_class, false, &t_class); if (t_success) t_success = MCStringAppendFormat(*t_info, "%@\n%@\n%@\n%u\n", t_license_name, t_license_org, *t_class, MClicenseparameters . license_multiplicity); if (MClicenseparameters . deploy_targets != 0) { bool t_first; t_first = true; for(uint32_t i = 0; t_success && i < sizeof(s_deploy_targets) / sizeof(s_deploy_targets[0]); i++) { if ((MClicenseparameters . deploy_targets & (1 << i)) != 0) { t_success = MCStringAppendFormat(*t_info, t_first ? "%s" : ",%s", s_deploy_targets[i]); t_first = false; } } } // AL-2014-11-04: [[ Bug 13865 ]] Don't add an extra line between deploy targets and addons if (t_success && MClicenseparameters . addons != nil) { MCAutoStringRef t_keys; t_success = (MCArrayListKeys(MClicenseparameters . addons, ',', &t_keys) && MCStringAppendFormat(*t_info, "\n%@", *t_keys)); } if (t_success) if (MCStringAppendFormat(*t_info, "\n%s", MCStringIsEmpty(MClicenseparameters . license_token) ? "Global" : "Local") && MCStringCopy(*t_info, r_info)) return; ctxt . Throw(); }
void MCArraysExecSplitByColumn(MCExecContext& ctxt, MCStringRef p_string, MCArrayRef& r_array) { MCStringRef t_row_delim, t_column_delim; t_row_delim = ctxt . GetRowDelimiter(); t_column_delim = ctxt . GetColumnDelimiter(); // Output array MCAutoArrayRef t_array; if (!MCArrayCreateMutable(&t_array)) { ctxt . Throw(); return; } // Temporary array for storing columns MCAutoArray<MCStringRef> t_temp_array; // Iterate over the rows of the input string uindex_t t_offset, t_length; t_offset = 0; t_length = MCStringGetLength(p_string); bool t_success; t_success = true; uindex_t t_row_index; t_row_index = 0; while (t_success && t_offset < t_length) { // Find the end of this row MCRange t_row_found; if (!MCStringFind(p_string, MCRangeMake(t_offset, UINDEX_MAX), t_row_delim, ctxt . GetStringComparisonType(), &t_row_found)) { t_row_found . offset = t_length; t_row_found . length = 0; } // Iterate over the cells of this row uindex_t t_cell_offset, t_column_index; t_cell_offset = t_offset; t_column_index = 0; while (t_success && t_cell_offset <= t_row_found . offset) { // Find the end of this cell MCRange t_cell_found; if (!MCStringFind(p_string, MCRangeMake(t_cell_offset, UINDEX_MAX), t_column_delim, ctxt . GetStringComparisonType(), &t_cell_found) || t_cell_found . offset > t_row_found . offset) { t_cell_found . offset = t_row_found . offset; // AL-2014-08-04: [[ Bug 13090 ]] Make sure cell offset is incremented eventually when the delimiter is not found t_cell_found . length = 1; } // Check that the output array has a slot for this column if (t_temp_array.Size() <= t_column_index) t_temp_array.Extend(t_column_index + 1); // Check that a string has been created to store this column MCRange t_range; t_range = MCRangeMake(t_cell_offset, t_cell_found . offset - t_cell_offset); if (t_temp_array[t_column_index] == nil) { t_success = MCStringCreateMutable(0, t_temp_array[t_column_index]); // AL-2014-08-04: [[ Bug 13090 ]] If we are creating a new column, make sure we pad with empty cells 'above' this one uindex_t t_rows = t_row_index; while (t_success && t_rows--) t_success = MCStringAppend(t_temp_array[t_column_index], t_row_delim); if (t_success) t_success = MCStringAppendFormat(t_temp_array[t_column_index], "%*@", &t_range, p_string); } else { // AL-2014-06-12: [[ Bug 12610 ]] Range parameter to MCStringFormat must be a pointer to an MCRange t_success = MCStringAppendFormat(t_temp_array[t_column_index], "%@%*@", t_row_delim, &t_range, p_string); } // Next cell t_column_index++; t_cell_offset = t_cell_found . offset + t_cell_found . length; } // AL-2014-08-04: [[ Bug 13090 ]] Pad the rest of this row with empty cells index_t t_pad_number; t_pad_number = t_temp_array . Size() - t_column_index; if (t_success && t_pad_number > 0) { while (t_success && t_pad_number--) t_success = MCStringAppend(t_temp_array[t_column_index++], t_row_delim); } // Next row t_row_index++; t_offset = t_row_found . offset + t_row_found . length; } // Convert the temporary array into a "proper" array for (uindex_t i = 0; i < t_temp_array.Size() && t_success; i++) { t_success = MCArrayStoreValueAtIndex(*t_array, i + 1, t_temp_array[i]); MCValueRelease(t_temp_array[i]); } if (t_success) t_success = MCArrayCopy(*t_array, r_array); if (!t_success) ctxt . Throw(); }
void MCFontBreakText(MCFontRef p_font, MCStringRef p_text, MCRange p_range, MCFontBreakTextCallback p_callback, void *p_callback_data, bool p_rtl) { // MW-2013-12-19: [[ Bug 11559 ]] If the font has a nil font, do nothing. if (p_font -> fontstruct == nil) return; // If the text is small enough, don't bother trying to break it /*if (p_length <= (kMCFontBreakTextCharLimit * (p_is_unicode ? 2 : 1))) { p_callback(p_font, p_text, p_length, p_is_unicode, p_callback_data); return; }*/ //p_callback(p_font, p_text, p_length, p_is_unicode, p_callback_data); //return; // Scan forward in the string for possible break locations. Breaks are // assigned a quality value as some locations are better for breaking than // others. The qualities are: // // 0. no break found // 1. grapheme break found // 2. URL break found ('/' char) // 3. word break found // // This isn't a particularly good algorithm but should suffice until full // Unicode support is added and a proper breaking algorithm implemented. uint32_t t_stride; t_stride = kMCFontBreakTextCharLimit; uindex_t t_end = p_range.offset + p_range.length; uindex_t t_length = p_range.length; uindex_t t_offset = (p_rtl) ? 0 : p_range.offset; while (t_length > 0) { int t_break_quality; uindex_t t_break_point, t_index; t_break_quality = 0; t_break_point = 0; t_index = 0; // Find the best break within the next stride characters. If there are // no breaking points, extend beyond the stride until one is found. while ((t_index < t_stride || t_break_quality == 0) && t_index < t_length) { codepoint_t t_char; uindex_t t_advance; if (p_rtl) t_char = MCStringGetCharAtIndex(p_text, t_end - t_index - t_offset); else t_char = MCStringGetCharAtIndex(p_text, t_offset + t_index); if (MCUnicodeCodepointIsHighSurrogate(t_char)) { // Surrogate pair if (p_rtl) t_char = MCUnicodeSurrogatesToCodepoint(t_char, MCStringGetCharAtIndex(p_text, t_end - t_index - t_offset - 1)); else t_char = MCUnicodeSurrogatesToCodepoint(t_char, MCStringGetCharAtIndex(p_text, t_offset + t_index + 1)); t_advance = 2; } else { t_advance = 1; } // Prohibit breaks at the beginning of the string if (t_index == 0) { t_index += t_advance; continue; } if (t_char == ' ') { t_break_point = t_index; t_break_quality = 3; } else if (t_break_quality < 3 && t_char == '/') { t_break_point = t_index; t_break_quality = 2; } else if (t_break_quality < 2 && MCUnicodeCodepointIsBase(t_char)) { t_break_point = t_index; t_break_quality = 1; } else if (t_break_quality < 2 && t_char > 0xFFFF) { // Character outside BMP, assume can break here t_break_point = t_index; t_break_quality = 1; } // If the break point is a word boundary, don't look for a later // breaking point. Words are cached as-is where possible. if (t_break_quality == 3) break; // Advance to the next character t_index += t_advance; } // If no word break was found and the whole of the remaining text was // searched and the remaining text is smaller than the break size then // don't attempt a break just for the sake of it. if (t_break_quality < 3 && t_length < kMCFontBreakTextCharLimit) t_break_point = t_length; // If no break point was found, just process the whole line if (t_break_quality == 0) t_break_point = t_length; // Process this chunk of text MCRange t_range; if (p_rtl) t_range = MCRangeMake(t_end - t_offset - t_break_point, t_break_point); else t_range = MCRangeMake(t_offset, t_break_point); #if !defined(_WIN32) && !defined(_ANDROID_MOBILE) // This is a really ugly hack to get LTR/RTL overrides working correctly - // ATSUI and Pango think they know better than us and won't let us suppress // the BiDi algorithm they uses for text layout. So instead, we need to add // an LRO or RLO character in front of every single bit of text :-( MCAutoStringRef t_temp; unichar_t t_override; if (p_rtl) t_override = 0x202E; else t_override = 0x202D; /* UNCHECKED */ MCStringCreateMutable(0, &t_temp); /* UNCHECKED */ MCStringAppendChar(*t_temp, t_override); /* UNCHECKED */ MCStringAppendSubstring(*t_temp, p_text, t_range); /* UNCHECKED */ MCStringAppendChar(*t_temp, 0x202C); p_callback(p_font, *t_temp, MCRangeMake(0, MCStringGetLength(*t_temp)), p_callback_data); #else // Another ugly hack - this time, to avoid incoming strings being coerced // into Unicode strings needlessly (because the drawing code uses unichars). // Do a mutable copy (to ensure an actual copy) before drawing. MCAutoStringRef t_temp; /* UNCHECKED */ MCStringMutableCopySubstring(p_text, t_range, &t_temp); p_callback(p_font, *t_temp, MCRangeMake(0, t_range.length), p_callback_data); #endif // Explicitly show breaking points //p_callback(p_font, MCSTR("|"), MCRangeMake(0, 1), p_callback_data); // Move on to the next chunk t_offset += t_break_point; // SN-2014-07-23: [[ Bug 12910 ]] Script editor crashes // Make sure we get 0 as a minimum, not a negative value since t_length is a uindex_t. if (t_length < t_break_point) t_length = 0; else t_length -= t_break_point; } }
static MCStringRef windows_convert_time_format(MCStringRef p_format) { MCStringRef t_output; MCStringCreateMutable(0, t_output); uindex_t t_offset = 0; while (t_offset < MCStringGetLength(p_format)) { unichar_t t_char; t_char = MCStringGetCharAtIndex(p_format, t_offset++); if (t_char == '\'') { // Copy quoted strings to the output with no conversion while ((t_char = MCStringGetCharAtIndex(p_format, t_offset++)) != '\'') MCStringAppendChar(t_output, t_char); } else { // Is this a day/month/year specifier? if (t_char == 'h' || t_char == 'H' || t_char == 'm' || t_char == 's' || t_char == 't') { // Count the number of consecutive identical characters unichar_t t_want = t_char; int t_count = 1; while ((t_char = MCStringGetCharAtIndex(p_format, t_offset)) == t_want) { t_count++; t_offset++; } // Append the correct formatting instruction switch (t_want) { case 'h': if (t_count == 1) MCStringAppendFormat(t_output, "%%#I"); else if (t_count == 2) MCStringAppendFormat(t_output, "%%I"); break; case 'H': if (t_count == 1) MCStringAppendFormat(t_output, "%%#H"); else if (t_count == 2) MCStringAppendFormat(t_output, "%%H"); break; case 'm': if (t_count == 1) MCStringAppendFormat(t_output, "%%#M"); else if (t_count == 2) MCStringAppendFormat(t_output, "%%M"); break; case 's': if (t_count == 1) MCStringAppendFormat(t_output, "%%#S"); else if (t_count == 2) MCStringAppendFormat(t_output, "%%S"); break; case 't': MCStringAppendFormat(t_output, "%%p"); } } else { // Unknown character, copy it to the output MCStringAppendChar(t_output, t_char); } } } MCValueRelease(p_format); return t_output; }
static MCStringRef windows_convert_date_format(MCStringRef p_format) { MCStringRef t_output; MCStringCreateMutable(0, t_output); uindex_t t_offset = 0; while (t_offset < MCStringGetLength(p_format)) { unichar_t t_char; t_char = MCStringGetCharAtIndex(p_format, t_offset++); if (t_char == '\'') { // Copy quoted strings to the output with no conversion while ((t_char = MCStringGetCharAtIndex(p_format, t_offset++)) != '\'') MCStringAppendChar(t_output, t_char); } else { // Is this a day/month/year specifier? if (t_char == 'd' || t_char == 'M' || t_char == 'y') { // Count the number of consecutive identical characters unichar_t t_want = t_char; int t_count = 1; while (MCStringGetCharAtIndex(p_format, t_offset) == t_want) { t_count++; t_offset++; } // Append the correct formatting instruction switch (t_char) { case 'd': if (t_count == 1) MCStringAppendFormat(t_output, "%%#d"); else if (t_count == 2) MCStringAppendFormat(t_output, "%%d"); else if (t_count == 3) MCStringAppendFormat(t_output, "%%a"); else if (t_count == 4) MCStringAppendFormat(t_output, "%%A"); break; case 'M': if (t_count == 1) MCStringAppendFormat(t_output, "%%#m"); else if (t_count == 2) MCStringAppendFormat(t_output, "%%m"); else if (t_count == 3) MCStringAppendFormat(t_output, "%%b"); else if (t_count == 4) MCStringAppendFormat(t_output, "%%B"); break; case 'y': if (t_count == 1) MCStringAppendFormat(t_output, "%%#y"); else if (t_count == 2) MCStringAppendFormat(t_output, "%%y"); else if (t_count == 4) MCStringAppendFormat(t_output, "%%Y"); break; } } else { // Unknown character, copy it to the output MCStringAppendChar(t_output, t_char); } } } MCValueRelease(p_format); return t_output; }