Ejemplo n.º 1
0
// 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);
}
Ejemplo n.º 2
0
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();
}
Ejemplo n.º 3
0
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);
	}
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
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();
}
Ejemplo n.º 7
0
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();
}
Ejemplo n.º 8
0
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;
    }
}
Ejemplo n.º 9
0
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;
}
Ejemplo n.º 10
0
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;
}