Esempio n. 1
0
static bool types_to_remote_types(char * const p_types[], uint4 p_type_count, char**& r_rtypes)
{
	char **t_rtypes;
	if (!MCMemoryNewArray(p_type_count * 2, t_rtypes))
		return false;

	for(uint32_t i = 0; i < p_type_count; i++)
	{
		uint32_t t_part_count;
		char **t_parts;
		if (MCCStringSplit(p_types[i], '|', t_parts, t_part_count))
		{
			if (t_part_count > 0)
			{
				MCCStringClone(t_parts[0], t_rtypes[i * 2]);
				if (t_part_count > 1)
					MCCStringClone(t_parts[1], t_rtypes[i * 2 + 1]);
			}
			MCCStringArrayFree(t_parts, t_part_count);
		}
	}

	r_rtypes = t_rtypes;

	return true;
}
Esempio n. 2
0
// Should be removed when 'combine by row' and 'combine by column' only differs by the delimiter used,
// not by the way the array is handled - any index is fine for combine by row
void MCArraysExecCombineByRow(MCExecContext& ctxt, MCArrayRef p_array, MCStringRef &r_string)
{
    MCAutoListRef t_list;
    MCListCreateMutable(ctxt . GetRowDelimiter(), &t_list);

    uindex_t t_count = MCArrayGetCount(p_array);
    combine_array_t t_lisctxt;
    bool t_success;

    t_lisctxt . elements = nil;
    t_lisctxt . index = 0;
    t_success = MCMemoryNewArray(t_count, t_lisctxt . elements);

    if (t_success)
    {
        MCArrayApply(p_array, list_array_elements, &t_lisctxt);
        qsort(t_lisctxt . elements, t_count, sizeof(array_element_t), compare_array_element);

        for (int i = 0; i < t_count && t_success; ++i)
        {
            MCAutoStringRef t_string;
            if (ctxt . ConvertToString(t_lisctxt . elements[i] . value, &t_string))
                t_success = MCListAppend(*t_list, *t_string);
            else
                t_success = false;
        }

        MCMemoryDeleteArray(t_lisctxt . elements);
    }

    if (t_success && MCListCopyAsString(*t_list, r_string))
        return;

    ctxt . Throw();
}
Esempio n. 3
0
static bool __MCValueRehashUniqueValues(index_t p_new_item_count)
{
	// Get the current capacity index.
	uindex_t t_new_capacity_idx;
	t_new_capacity_idx = s_unique_value_capacity_idx;
	if (p_new_item_count != 0)
	{
		// If we are shrinking we just shrink down to the level needed by the currently
		// used buckets.
		if (p_new_item_count < 0)
			p_new_item_count = 0;

		// Work out the smallest possible capacity greater than the requested capacity.
		uindex_t t_new_capacity_req;
		t_new_capacity_req = s_unique_value_count + p_new_item_count;
		for(t_new_capacity_idx = 0; t_new_capacity_idx < 64; t_new_capacity_idx++)
			if (t_new_capacity_req <= __kMCValueHashTableCapacities[t_new_capacity_idx])
				break;
	}

	// Fetch the old capacity and table.
	uindex_t t_old_capacity;
	__MCUniqueValueBucket *t_old_buckets;
	t_old_capacity = __kMCValueHashTableSizes[s_unique_value_capacity_idx];
	t_old_buckets = s_unique_values;

	// Create the new table.
	uindex_t t_new_capacity;
	__MCUniqueValueBucket *t_new_buckets;
	t_new_capacity = __kMCValueHashTableSizes[t_new_capacity_idx];
	if (!MCMemoryNewArray(t_new_capacity, t_new_buckets))
		return false;

	// Update the vars.
	s_unique_value_capacity_idx = t_new_capacity_idx;
	s_unique_values = t_new_buckets;

	// Now rehash the values from the old table.
	for(uindex_t i = 0; i < t_old_capacity; i++)
	{
		if (t_old_buckets[i] . value != UINTPTR_MIN && t_old_buckets[i] . value != UINTPTR_MAX)
		{
			uindex_t t_target_slot;
			t_target_slot = __MCValueFindUniqueValueBucketAfterRehash((__MCValue *)t_old_buckets[i] . value, t_old_buckets[i] . hash);

			// This assertion should never trigger - something is very wrong if it does!
			MCAssert(t_target_slot != UINDEX_MAX);

			s_unique_values[t_target_slot] . hash = t_old_buckets[i] . hash;
			s_unique_values[t_target_slot] . value = t_old_buckets[i] . value;
		}
	}

	// Delete the old table.
	MCMemoryDeleteArray(t_old_buckets);

	// We are done!
	return true;
}
Esempio n. 4
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();
}
Esempio n. 5
0
bool MCResampledImageRep::LoadImageFrames(MCBitmapFrame *&r_frames, uindex_t &r_frame_count, bool &r_frames_premultiplied)
{
	uindex_t t_src_width, t_src_height;
	if (!m_source->GetGeometry(t_src_width, t_src_height))
		return false;
	
	bool t_success = true;
	
	MCBitmapFrame *t_frames = nil;
	uindex_t t_frame_count = 0;
	
	t_frame_count = m_source->GetFrameCount();
	
	// IM-2013-07-03: [[ Bug 11018 ]] fail here if the source has no frames
	t_success = t_frame_count != 0;

	if (t_success)
		t_success = MCMemoryNewArray(t_frame_count, t_frames);
	
	MCGFloat t_scale;
	t_scale = MCMax(m_target_width / (float)t_src_width, m_target_height / (float)t_src_height);
	
	for (uindex_t i = 0; t_success && i < t_frame_count; i++)
	{
		MCBitmapFrame *t_src_frame = nil;
		
		t_success = m_source->LockBitmapFrame(i, t_scale, t_src_frame);
		if (t_success)
		{
			t_frames[i].duration = t_src_frame->duration;
			
			t_success = MCImageScaleBitmap(t_src_frame->image, m_target_width, m_target_height, INTERPOLATION_BICUBIC, t_frames[i].image);
			if (t_success)
				MCImageFlipBitmapInPlace(t_frames[i].image, m_h_flip, m_v_flip);
		}
		m_source->UnlockBitmapFrame(i, t_src_frame);
	}
	
	if (t_success)
	{
		r_frames = t_frames;
		r_frame_count = t_frame_count;
		r_frames_premultiplied = false;
	}
	else
		MCImageFreeFrames(t_frames, t_frame_count);
	
	return t_success;
}
Esempio n. 6
0
bool rle_true_encode(const uint4 *sptr, uint4 ssize, uint1 *&dptr, uint4 &dsize)
{
    uint4 osize = ssize + (ssize / 127);
    uint1 *destptr = nil;
    if (!MCMemoryNewArray(osize, destptr))
        return false;
    const uint4 *eptr = sptr + ssize / sizeof(uint4);
    dsize = 0;
    uint2 run;
    do
    {
        run = 1;
        if (sptr < (eptr - 1) && *sptr == *(sptr + 1))
        {
            uint4 pixel = *sptr;
            while (++sptr < eptr && *sptr == pixel && run < 127)
                run++;
            destptr[dsize++] = run | 0x80;
            swap_uint4(&pixel);
            memcpy(&destptr[dsize], &pixel, sizeof(uint4));
            dsize += sizeof(uint4);
        }
        else
        {
            while (++sptr < (eptr - 1) && *sptr != *(sptr + 1) && run < 127)
                run++;
            destptr[dsize++] = (uint1)run;
            uint2 bytes = run * sizeof(uint4);
            memcpy(&destptr[dsize], sptr - run, bytes);
            uint4 *startptr = (uint32_t*)&destptr[dsize];
            while (run--)
                swap_uint4(startptr++);
            dsize += bytes;
        }
    }
    while (sptr < eptr);

    if (!MCMemoryReallocate(destptr, dsize, dptr))
    {
        MCMemoryDeleteArray(destptr);
        return false;
    }

    return true;
}
Esempio n. 7
0
static bool WindowsGetModuleFileNameEx(HANDLE p_process, HMODULE p_module, MCStringRef& r_path)
{
	bool t_success;
	t_success = true;

	// For some unfathomable reason, it is not possible find out how big a
	// buffer you might need for a module file name. Instead we loop until
	// we are sure we have the whole thing.
	WCHAR *t_path;
	uint32_t t_path_length;
	t_path_length = 0;
	t_path = nil;
	while(t_success)
	{
		t_path_length += 256;
		MCMemoryDeleteArray(t_path);

		if (t_success)
			t_success = MCMemoryNewArray(t_path_length, t_path);

		DWORD t_result;
		t_result = 0;
		if (t_success)
		{
			// If the buffer is too small, the result will equal the input
			// buffer size.
			t_result = GetModuleFileNameExW(p_process, p_module, t_path, t_path_length);
			if (t_result == 0)
				t_success = false;
			else if (t_result == t_path_length)
				continue;
		}

		if (t_success)
			break;
	}

	if (t_success)
		t_success = MCStringCreateWithWString(t_path, r_path);
	
	MCMemoryDeleteArray(t_path);

	return t_success;
}
Esempio n. 8
0
bool MCWin32QueryActCtxSettings(const unichar_t *p_settings_name, unichar_t *&r_value)
{
	bool t_success;
	t_success = true;

	BOOL t_result;
	SIZE_T t_size;

	unichar_t *t_buffer;
	t_buffer = NULL;

	uint32_t t_buffer_size;
	t_buffer_size = 0;

	t_success = MCWin32QueryActCtxSettingsW(t_result, 0, NULL, NULL, p_settings_name, NULL, 0, &t_size);

	if (t_success)
	{
		DWORD t_error;
		t_error = GetLastError();
		t_success = t_result != FALSE;
		t_success = t_result == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER;
	}

	if (t_success)
	{
		t_buffer_size = t_size;
		t_success = MCMemoryNewArray(t_buffer_size, t_buffer);
	}

	if (t_success)
		t_success = MCWin32QueryActCtxSettingsW(t_result, 0, NULL, NULL, p_settings_name, t_buffer, t_buffer_size, &t_size);

	if (t_success)
		t_success = t_result != FALSE;

	if (t_success)
		r_value = t_buffer;
	else
		MCMemoryDeleteArray(t_buffer);

	return t_success;
}
Esempio n. 9
0
bool __MCValueInitialize(void)
{
    if (!MCMemoryNewArray(kMCValueTypeCodeList + 1, s_value_pools))
        return false;
    
	if (!__MCValueCreate(kMCValueTypeCodeNull, kMCNull))
		return false;

	if (!__MCValueCreate(kMCValueTypeCodeBoolean, kMCTrue))
		return false;
	
	if (!__MCValueCreate(kMCValueTypeCodeBoolean, kMCFalse))
		return false;

	if (!__MCValueRehashUniqueValues(1))
		return false;
    
	return true;
}
Esempio n. 10
0
// IM-2014-01-29: [[ HiDPI ]] Refactored to handle display info caching in MCUIDC superclass
bool MCScreenDC::device_getdisplays(bool p_effective, MCDisplay * &r_displays, uint32_t &r_display_count)
{
	// NOTE: this code assumes that there is only one GdkScreen!
    GdkScreen *t_screen;
    t_screen = gdk_display_get_default_screen(dpy);
    
    // Get the number of monitors attached to this screen
    gint t_monitor_count;
    t_monitor_count = gdk_screen_get_n_monitors(t_screen);
    
    // Allocate the list of monitors
    MCDisplay *t_displays;
    MCMemoryNewArray(t_monitor_count, t_displays);
    
    // Get the geometry of each monitor
    for (gint i = 0; i < t_monitor_count; i++)
    {
        GdkRectangle t_rect;
        gdk_screen_get_monitor_geometry(t_screen, i, &t_rect);
        
        MCRectangle t_mc_rect;
        t_mc_rect = MCRectangleMake(t_rect.x, t_rect.y, t_rect.width, t_rect.height);
        
        t_displays[i].index = i;
        t_displays[i].pixel_scale = 1.0;
        t_displays[i].viewport = t_displays[i].workarea = t_mc_rect;
    }
    
    if (t_monitor_count == 1)
    {
        apply_workarea(t_displays, t_monitor_count) || apply_partial_struts(t_displays, t_monitor_count);
    }
    else
    {
        apply_partial_struts(t_displays, t_monitor_count);
    }
    
    // All done
    r_displays = t_displays;
    r_display_count = t_monitor_count;
    return true;
}
Esempio n. 11
0
bool MCSessionReadIndex(MCSessionIndexRef p_index)
{
	bool t_success = true;
	
	t_success = read_uint32(p_index->file, p_index->session_count);
	if (t_success)
		t_success = MCMemoryNewArray(p_index->session_count, p_index->session);

	for (uint32_t i = 0; t_success && i < p_index->session_count; i++)
	{
		t_success = MCMemoryNew(p_index->session[i]);
		if (t_success)
			t_success = read_cstring(p_index->file, p_index->session[i]->id) &&
						read_cstring(p_index->file, p_index->session[i]->ip) &&
						read_cstring(p_index->file, p_index->session[i]->filename) &&
						read_real64(p_index->file, p_index->session[i]->expires);
	}

	return t_success;
}
Esempio n. 12
0
bool MCCompressedImageRep::LoadImageFrames(MCImageFrame *&r_frames, uindex_t &r_frame_count, bool &r_frames_premultiplied)
{
	bool t_success = true;

	MCImageFrame *t_frame = nil;
	t_success = MCMemoryNewArray(1, t_frame);
	if (t_success)
		t_success = MCImageDecompressRLE(m_compressed, t_frame->image);

	if (t_success)
	{
		t_frame->density = 1.0;
		
		r_frames = t_frame;
		r_frame_count = 1;
		r_frames_premultiplied = false;
	}
	else
		MCImageFreeFrames(t_frame, 1);

	return t_success;
}
Esempio n. 13
0
// decode image data to a series of frames, ignoring all the other bits & pieces
bool MCImageDecode(IO_handle p_stream, MCImageFrame *&r_frames, uindex_t &r_frame_count)
{
	bool t_success = true;

	MCImageFrame *t_frames = nil;
	uindex_t t_frame_count = 0;

	MCImageBitmap *t_bitmap = nil;
	MCImageCompressedBitmap *t_compressed = nil;

	MCPoint t_hotspot;
	char *t_name = nil;

	if (t_success)
		t_success = MCImageImport(p_stream, nil, t_hotspot, t_name, t_compressed, t_bitmap);

	if (t_success)
	{
		if (t_compressed != nil)
			t_success = MCImageDecompress(t_compressed, r_frames, r_frame_count);
		else
		{
			t_success = MCMemoryNewArray(1, r_frames);
			if (t_success)
			{
				r_frames[0].image = t_bitmap;
				t_bitmap = nil;
				r_frame_count = 1;
			}
		}
	}

	MCImageFreeCompressedBitmap(t_compressed);
	MCImageFreeBitmap(t_bitmap);
	MCCStringFree(t_name);

	return t_success;
}
Esempio n. 14
0
bool MCEventQueuePostImeCompose(MCStack *p_stack, bool p_enabled, uint32_t p_offset, const uint16_t *p_chars, uint32_t p_char_count)
{
	uint16_t *t_new_chars;
	if (!MCMemoryNewArray(p_char_count, t_new_chars))
		return false;

	MCEvent *t_event;
	if (!MCEventQueuePost(kMCEventTypeImeCompose, t_event))
	{
		MCMemoryDeleteArray(t_new_chars);
		return false;
	}

	t_event -> ime . stack = p_stack;
	t_event -> ime . compose . enabled = p_enabled;
	t_event -> ime . compose . offset = p_offset;
	t_event -> ime . compose . chars = t_new_chars;
	t_event -> ime . compose . char_count = p_char_count;

	MCMemoryCopy(t_new_chars, p_chars, sizeof(uint16_t) * p_char_count);

	return true;
}
Esempio n. 15
0
bool MCGCacheTableCreate(uindex_t p_size, uindex_t p_max_occupancy, uindex_t p_max_bytes, MCGCacheTableRef &r_cache_table)
{
	bool t_success;
	t_success = true;
	
	__MCGCacheTable *t_cache_table;
	t_cache_table = NULL;
	if (t_success)
		t_success = MCMemoryNew(t_cache_table);
	
	__MCGCacheTableEntry *t_pairs;
	t_pairs = NULL;
	if (t_success)
		t_success = MCMemoryNewArray(p_size, t_pairs);
	
	if (t_success)
	{
		t_cache_table -> total_buckets = p_size;
		t_cache_table -> used_buckets = 0;
		t_cache_table -> max_occupancy = p_max_occupancy;
		t_cache_table -> max_bytes = p_max_bytes;
		t_cache_table -> bytes_used = sizeof(__MCGCacheTable) + sizeof(__MCGCacheTableEntry) * p_size;
		t_cache_table -> pairs = t_pairs;
		
		t_success =  p_max_bytes > t_cache_table -> bytes_used;
	}
	
	if (t_success)
		r_cache_table = t_cache_table;
	else
	{
		MCMemoryDeleteArray(t_pairs);
		MCMemoryDelete(t_cache_table);
	}
	
	return t_success;
}
Esempio n. 16
0
bool MCScreenDC::listprinters(MCStringRef& r_printers)
{
	MCAutoListRef t_list;
	if (!MCListCreateMutable('\n', &t_list))
		return false;

	DWORD t_flags;
	DWORD t_level;
	t_flags = PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS;
	t_level = 4;

	DWORD t_printer_count;
	DWORD t_bytes_needed;
	t_printer_count = 0;
	t_bytes_needed = 0;
	if (EnumPrintersW(t_flags, NULL, t_level, NULL, 0, &t_bytes_needed, &t_printer_count) != 0 || GetLastError() == ERROR_INSUFFICIENT_BUFFER)
	{
		MCAutoPointer<byte_t> t_printers;
		if (!MCMemoryNewArray(t_bytes_needed, &t_printers))
			return false;

		if (EnumPrintersW(t_flags, NULL, t_level, (LPBYTE)*t_printers, t_bytes_needed, &t_bytes_needed, &t_printer_count) != 0)
		{
			for(uint4 i = 0; i < t_printer_count; ++i)
			{
				MCAutoStringRef t_printer_name;
				if (!MCStringCreateWithWString(((PRINTER_INFO_4W *)*t_printers)[i] . pPrinterName, &t_printer_name))
					return false;
				if (!MCListAppend(*t_list, *t_printer_name))
					return false;
			}
		}
	}

	return MCListCopyAsString(*t_list, r_printers);
}
Esempio n. 17
0
bool MCEncodedImageRep::LoadImageFrames(MCImageFrame *&r_frames, uindex_t &r_frame_count, bool &r_frames_premultiplied)
{
	bool t_success = true;

	// IM-2013-02-18 - switching this back to using MCImageImport as we need to
	// determine the compression type for m_compression

	IO_handle t_stream = nil;
	IO_handle t_mask_stream = nil;

	MCImageCompressedBitmap *t_compressed = nil;
	MCImageBitmap *t_bitmap = nil;

	MCPoint t_hotspot = {1, 1};
	char *t_name = nil;

	t_success = GetDataStream(t_stream) &&
		MCImageImport(t_stream, t_mask_stream, t_hotspot, t_name, t_compressed, t_bitmap);

	if (t_stream != nil)
		MCS_close(t_stream);

	MCImageFrame *t_frames;
	t_frames = nil;
	
	uindex_t t_frame_count;
	t_frame_count = 0;
	
	if (t_success)
	{
		if (t_compressed != nil)
			t_success = MCImageDecompress(t_compressed, t_frames, t_frame_count);
		else
		{
			t_success = MCMemoryNewArray(1, t_frames);
			if (t_success)
			{
				t_frames[0].image = t_bitmap;
				t_frames[0].density = 1.0;
				t_bitmap = nil;
				t_frame_count = 1;
			}
		}
	}

	if (t_success)
	{

		m_width = t_frames[0].image->width;
		m_height = t_frames[0].image->height;

		if (t_compressed != nil)
			m_compression = t_compressed->compression;

		m_have_geometry = true;
		
		r_frames = t_frames;
		r_frame_count = t_frame_count;
		r_frames_premultiplied = false;
	}

	MCCStringFree(t_name);
	
	MCImageFreeBitmap(t_bitmap);
	MCImageFreeCompressedBitmap(t_compressed);

	return t_success;
}
Esempio n. 18
0
IO_stat MCLogicalFontTableLoad(IO_handle p_stream)
{
	// Delete any existing font table.
	MCLogicalFontTableFinish();

	// Keep track of any IO errors.
	IO_stat t_stat;
	t_stat = IO_NORMAL;

	// Read the number of entries.
	uint2 t_count;
	if (t_stat == IO_NORMAL)
		t_stat = IO_read_uint2(&t_count, p_stream);

	// Allocate an array big enough to hold all of them.
	if (t_stat == IO_NORMAL)
		if (!MCMemoryNewArray(t_count, s_logical_font_table))
			t_stat = IO_ERROR;

	if (t_stat == IO_NORMAL)
	{
		// The size and capacity of the table are equal to the count.
		s_logical_font_table_size = s_logical_font_table_capacity = t_count;

		// Iterate t_count times to load each entry in.
		for(uint32_t i = 0; i < t_count && t_stat == IO_NORMAL; i++)
		{
			char *t_textfont;
			uint2 t_textsize, t_textstyle;
			t_textfont = nil;

			// Read in the textSize, textStyle and (original) textFont props.
			t_stat = IO_read_uint2(&t_textsize, p_stream);
			if (t_stat == IO_NORMAL)
				t_stat = IO_read_uint2(&t_textstyle, p_stream);
			if (t_stat == IO_NORMAL)
				t_stat = IO_read_string(t_textfont, p_stream);

			// Now convert the textFont string into a name, splitting off the
			// lang tag (if any).
			MCNameRef t_textfont_name;
			bool t_is_unicode;
			if (t_stat == IO_NORMAL)
			{
				// MW-2012-02-17: [[ Bug ]] It seems possible for the textFont string
				//   to be empty in some cases - so handle this case carefully.
				const char *t_textfont_tag;
				if (t_textfont != nil)
				{
					t_textfont_tag = strchr(t_textfont, ',');
					if (t_textfont_tag == nil)
					{
						t_textfont_tag = t_textfont + strlen(t_textfont);
						t_is_unicode = false;
					}
					else
						t_is_unicode = true;
				}
				else
				{
					t_textfont_tag = nil;
					t_is_unicode = false;
				}

				if (!MCNameCreateWithOldString(MCString(t_textfont, t_textfont_tag - t_textfont), t_textfont_name))
					t_stat = IO_ERROR;
			}

			// Set the appropriate table entry.
			if (t_stat == IO_NORMAL)
				MCLogicalFontTableSetEntry(i, t_textfont_name, t_textstyle, t_textsize, t_is_unicode);

			// Cleanup the (temporary) original textFont string.
			delete t_textfont;
		}
	}

	return t_stat;
}
Esempio n. 19
0
// This method reads a stack from the given stream. The stack is set to
// have parent MCDispatch, and filename MCcmd. It is designed to be used
// for embedded stacks/deployed stacks/revlet stacks.
IO_stat MCDispatch::readstartupstack(IO_handle stream, MCStack*& r_stack)
{
	char version[8];
	uint1 charset, type;
	char *newsf;
	if (readheader(stream, version) != IO_NORMAL
	        || IO_read_uint1(&charset, stream) != IO_NORMAL
	        || IO_read_uint1(&type, stream) != IO_NORMAL
	        || IO_read_string(newsf, stream) != IO_NORMAL)
		return IO_ERROR;

	// MW-2008-10-20: [[ ParentScripts ]] Set the boolean flag that tells us whether
	//   parentscript resolution is required to false.
	s_loaded_parent_script_reference = false;

	MCtranslatechars = charset != CHARSET;
	delete newsf; // stackfiles is obsolete

	MCStack *t_stack = nil;
	/* UNCHECKED */ MCStackSecurityCreateStack(t_stack);
	t_stack -> setparent(this);
	
	// MM-2013-10-30: [[ Bug 11333 ]] Set the filename of android mainstack to apk/mainstack (previously was just apk).
	//   This solves relative file path referencing issues.
#ifdef TARGET_SUBPLATFORM_ANDROID
    char *t_filename;
    /* UNCHECKED */ MCMemoryNewArray(MCCStringLength(MCcmd) + 11, t_filename);
    MCCStringFormat(t_filename, "%s/mainstack", MCcmd);
	t_stack -> setfilename(t_filename);
#else
   	t_stack -> setfilename(strclone(MCcmd));
#endif
	
	
	if (IO_read_uint1(&type, stream) != IO_NORMAL
	        || type != OT_STACK && type != OT_ENCRYPT_STACK
	        || t_stack->load(stream, version, type) != IO_NORMAL)
	{
		delete t_stack;
		return IO_ERROR;
	}

	if (t_stack->load_substacks(stream, version) != IO_NORMAL
	        || IO_read_uint1(&type, stream) != IO_NORMAL
	        || type != OT_END)
	{
		delete t_stack;
		return IO_ERROR;
	}

	// We are reading the startup stack, so this becomes the root of the
	// stack list.
	stacks = t_stack;

	r_stack = t_stack;

#ifndef _MOBILE
	// Make sure parent script references are up to date.
	if (s_loaded_parent_script_reference)
		t_stack -> resolveparentscripts();
#else
	// Mark the stack as needed parentscript resolution. This is done after
	// aux stacks have been loaded.
	if (s_loaded_parent_script_reference)
		t_stack -> setextendedstate(True, ECS_USES_PARENTSCRIPTS);
#endif

	return IO_NORMAL;
}
Esempio n. 20
0
Exec_stat MCIdeDmgBuild::exec(MCExecPoint& ep)
{
	Exec_stat t_stat;
	t_stat = ES_NORMAL;

	// Clear the result as we return an error there
	MCresult -> clear();

	/////////

	if (t_stat == ES_NORMAL)
		t_stat = m_items -> eval(ep);
		
	if (t_stat == ES_NORMAL && ep . getformat() != VF_ARRAY)
		t_stat = ES_ERROR;

	MCVariableArray *t_array;
	if (t_stat == ES_NORMAL)
	{
		t_array = ep . getarray() -> get_array();
		if (!t_array -> issequence())
			t_stat = ES_ERROR;
	}

	MCDeployDmgItem *t_items;
	uint32_t t_item_count;
	t_items = nil;
	t_item_count = 0;
	if (t_stat == ES_NORMAL)
	{
		if (MCMemoryNewArray(t_array -> getnfilled(), t_items))
			t_item_count = t_array -> getnfilled();
		else
			t_stat = ES_ERROR;
	}

	MCExecPoint ep2(ep);
	if (t_stat == ES_NORMAL)
		for(uint32_t i = 0; i < t_item_count && t_stat == ES_NORMAL; i++)
		{
			MCHashentry *t_element;
			t_element = t_array -> lookupindex(i + 1, False);
			if (t_element == nil)
				t_stat = ES_ERROR;

			if (t_stat == ES_NORMAL)
				t_stat = t_element -> value . fetch(ep2);

			MCVariableValue *t_item_array;
			if (t_stat == ES_NORMAL)
			{
				t_item_array = ep2 . getarray();
				if (t_item_array == nil)
					t_stat = ES_ERROR;
			}

			if (t_stat == ES_NORMAL)
			{
				t_stat = t_item_array -> fetch_element(ep2, "type");
				if (t_stat == ES_NORMAL)
				{
					if (ep2 . getsvalue() == "folder")
						t_items[i] . is_folder = true;
					else if (ep2 . getsvalue() == "file")
						t_items[i] . is_folder = false;
					else
						t_stat = ES_ERROR;
				}
			}

			if (t_stat == ES_NORMAL)
				t_stat = fetch_uint32(ep2, t_item_array, "parent", t_items[i] . parent);
			if (t_stat == ES_NORMAL)
				t_stat = fetch_cstring(ep2, t_item_array, "name", t_items[i] . name);

			if (t_stat == ES_NORMAL)
				t_stat = fetch_opt_uint32(ep2, t_item_array, "owner_id", t_items[i] . owner_id);
			if (t_stat == ES_NORMAL)
				t_stat = fetch_opt_uint32(ep2, t_item_array, "group_id", t_items[i] . group_id);
			if (t_stat == ES_NORMAL)
				t_stat = fetch_opt_uint32(ep2, t_item_array, "file_mode", t_items[i] . file_mode);

			if (t_stat == ES_NORMAL)
				t_stat = fetch_opt_uint32(ep2, t_item_array, "create_date", t_items[i] . create_date);
			if (t_stat == ES_NORMAL)
				t_stat = fetch_opt_uint32(ep2, t_item_array, "content_mod_date", t_items[i] . content_mod_date);
			if (t_stat == ES_NORMAL)
				t_stat = fetch_opt_uint32(ep2, t_item_array, "attribute_mod_date", t_items[i] . attribute_mod_date);
			if (t_stat == ES_NORMAL)
				t_stat = fetch_opt_uint32(ep2, t_item_array, "access_date", t_items[i] . access_date);
			if (t_stat == ES_NORMAL)
				t_stat = fetch_opt_uint32(ep2, t_item_array, "backup_date", t_items[i] . backup_date);
		}

	/////////

	if (t_stat == ES_NORMAL)
		t_stat = m_filename -> eval(ep);

	if (t_stat == ES_NORMAL)
	{
		MCDeployDmgParameters t_params;
		t_params . items = t_items;
		t_params . item_count = t_item_count;
		t_params . output = (char *)ep . getcstring();
		if (!MCDeployDmgBuild(t_params))
			t_stat = ES_ERROR;
	}

	////////

	for(uint32_t i = 0; i < t_item_count; i++)
		MCCStringFree(t_items[i] . name);
	MCMemoryDeleteArray(t_items);

	return ES_NORMAL;
}
Esempio n. 21
0
// This method constructs and then writes out a capsule to the given output file.
// The capsule contents is derived from the deploy parameters structure.
// The offset in the file after writing is returned in x_offset.
bool MCDeployWriteCapsule(const MCDeployParameters& p_params, MCDeployFileRef p_output, uint32_t& x_offset)
{
	bool t_success;
	t_success = true;

	// Open the stackfile.
	MCDeployFileRef t_stackfile;
	t_stackfile = NULL;
	if (t_success && !MCDeployFileOpen(p_params . stackfile, "rb", t_stackfile))
		t_success = MCDeployThrow(kMCDeployErrorNoStackfile);

	// Open the spill file, if required
	MCDeployFileRef t_spill;
	t_spill = NULL;
	if (t_success && p_params . spill != nil && !MCDeployFileOpen(p_params . spill, "wb+", t_spill))
		t_success = MCDeployThrow(kMCDeployErrorNoSpill);

	// First create our deployment capsule
	MCDeployCapsuleRef t_capsule;
	t_capsule = nil;
	if (t_success)
		t_success = MCDeployCapsuleCreate(t_capsule);

	// Next, the first thing to do is to add the the header section.
	if (t_success)
		t_success = MCDeployWriteCapsuleDefineStandaloneSections(p_params, t_capsule);

	// Add any redirects
	if (t_success)
		for(uint32_t i = 0; i < p_params . redirect_count && t_success; i++)
			t_success = MCDeployCapsuleDefine(t_capsule, kMCCapsuleSectionTypeRedirect, p_params . redirects[i], MCCStringLength(p_params . redirects[i]) + 1);

	// Now we add the main stack
	if (t_success)
		t_success = MCDeployCapsuleDefineFromFile(t_capsule, kMCCapsuleSectionTypeStack, t_stackfile);

	// Now we add the auxillary stackfiles, if any
	MCDeployFileRef *t_aux_stackfiles;
	t_aux_stackfiles = nil;
	if (t_success)
		t_success = MCMemoryNewArray(p_params . auxillary_stackfile_count, t_aux_stackfiles);
	if (t_success)
		for(uint32_t i = 0; i < p_params . auxillary_stackfile_count && t_success; i++)
		{
			if (t_success && !MCDeployFileOpen(p_params . auxillary_stackfiles[i], "rb", t_aux_stackfiles[i]))
				t_success = MCDeployThrow(kMCDeployErrorNoAuxStackfile);
			if (t_success)
				t_success = MCDeployCapsuleDefineFromFile(t_capsule, kMCCapsuleSectionTypeAuxillaryStack, t_aux_stackfiles[i]);
		}
	
	// Now add the externals, if any
	if (t_success)
		for(uint32_t i = 0; i < p_params . external_count && t_success; i++)
			t_success = MCDeployCapsuleDefine(t_capsule, kMCCapsuleSectionTypeExternal, p_params . externals[i], MCCStringLength(p_params . externals[i]) + 1);

	// Now add the startup script, if any.
	if (t_success && p_params . startup_script != nil)
		t_success = MCDeployCapsuleDefine(t_capsule, kMCCapsuleSectionTypeStartupScript, p_params . startup_script, MCCStringLength(p_params . startup_script) + 1);

	// Now a digest
	if (t_success)
		t_success = MCDeployCapsuleChecksum(t_capsule);

	// Finally the epilogue
	if (t_success)
		t_success = MCDeployCapsuleDefine(t_capsule, kMCCapsuleSectionTypeEpilogue, nil, 0);

	// Now we write it
	if (t_success)
		t_success = MCDeployCapsuleGenerate(t_capsule, p_output, t_spill, x_offset);

	MCDeployCapsuleDestroy(t_capsule);
	for(uint32_t i = 0; i < p_params . auxillary_stackfile_count; i++)
		MCDeployFileClose(t_aux_stackfiles[i]);
	MCMemoryDeleteArray(t_aux_stackfiles);
	MCDeployFileClose(t_spill);
	MCDeployFileClose(t_stackfile);

	return t_success;
}
Esempio n. 22
0
bool MCSystemPickOption(const_cstring_array_t **p_expression, const_int32_array_t *p_indexes, uint32_t p_expression_cnt, const_int32_array_t *&r_result, bool p_use_checkmark, bool p_use_picker, bool p_use_cancel, bool p_use_done, bool &r_canceled, MCRectangle p_button_rect)
{
    MCLog("indexes: (%p) {length = %d, element[0] = %d}", p_indexes, p_indexes ? p_indexes->length : 0, p_indexes && p_indexes->length > 0 ? p_indexes->elements[0] : 0); 
    // multi-pick list not supported
    if (p_expression_cnt != 1)
        return false;
    
    bool t_success = true;
    // convert cstring array to java list of strings
    
    JNIEnv *t_env = MCJavaGetThreadEnv();
    jobject t_joptionlist = nil;
    const char *t_title = nil;
    bool t_has_selection = false;
    uint32_t t_selected_index = 0;
    
    t_success = MCJavaInitList(t_env, t_joptionlist);
    
    if (t_success)
    {
        for (uint32_t i = 0; t_success && i < p_expression[0]->length; i++)
        {
            MCString t_string(p_expression[0]->elements[i]);
            t_success = MCJavaListAppendString(t_env, t_joptionlist, &t_string);
        }
    }
    
    if (t_success)
    {
        t_has_selection = (p_indexes != nil && p_indexes->length != 0);
        if (t_has_selection)
            t_selected_index = p_indexes->elements[0];
        
        MCLog("selected index: %d", t_selected_index);
        s_in_popup_dialog = true;
        s_dialog_result = kMCDialogResultUnknown;
        MCAndroidEngineRemoteCall("showListPicker", "vlsbibbb", nil, t_joptionlist, t_title, t_has_selection, t_selected_index, p_use_checkmark, p_use_cancel, p_use_done);
    
        while (s_in_popup_dialog)
            MCscreen->wait(60.0, True, True);
        
        if (s_dialog_result == kMCDialogResultError)
            t_success = false;
        
        r_canceled = s_dialog_result == kMCDialogResultCanceled;
        if (!r_canceled)
        {
            t_success = MCMemoryNew(r_result) && MCMemoryNewArray(1, r_result->elements);
            if (t_success)
            {
                r_result->length = 1;
                r_result->elements[0] = s_selected_index + 1;
            }
        }

    }
    
    if (t_joptionlist != nil)
        MCJavaFreeList(t_env, t_joptionlist);
    
    return t_success;
}
Esempio n. 23
0
bool MCTextLayout(const unichar_t *p_chars, uint32_t p_char_count, MCFontStruct *p_font, MCTextLayoutCallback p_callback, void *p_context)
{
	bool t_success;
	t_success = true;

	// The state structure we use to record the list of runs and the dc we use
	// for processing.
	MCTextLayoutState self;
	MCMemoryClear(&self, sizeof(MCTextLayoutState));

	if (t_success)
	{
		self . dc = CreateCompatibleDC(nil);
		if (self . dc == nil)
			t_success = false;
	}

	// Fetch a layout font for the provided HFONT.
	if (t_success)
		t_success = MCTextLayoutFontFromHFONT(p_font -> fid, self . primary_font);

	// First thing we need to do is itemize the input string. The ScriptItemize
	// function splits up the chars into runs, each run being potentially
	// processed differently by Uniscribe.
	// Unfortunately, there is no way to predict for an arbitrary string how
	// many items might be generated, nor is the ScriptItemize function
	// incremental, thus we must loop with an every increasing buffer until
	// we have enough room.
	SCRIPT_ITEM *t_items;
	uint32_t t_item_limit, t_item_count;
	SCRIPT_STATE t_script_state;
	SCRIPT_CONTROL t_script_control;
	t_items = nil;
	t_item_limit = 0;
	t_item_count = 0;
	MCMemoryClear(&t_script_state, sizeof(SCRIPT_STATE));
	MCMemoryClear(&t_script_control, sizeof(SCRIPT_CONTROL));
	while(t_success)
	{
		// Increase the item array by 32 each time
		if (t_success)
			t_success = MCMemoryResizeArray(t_item_limit + 32, t_items, t_item_limit);
		
		// Attempt to itemize
		HRESULT t_result;
		if (t_success)
		{
			t_result = ScriptItemize(p_chars, p_char_count, t_item_limit, &t_script_control, &t_script_state, t_items, (int *)&t_item_count);
			if (t_result != S_OK && t_result != E_OUTOFMEMORY)
				t_success = false;
		}

		if (t_success && t_result == S_OK)
			break;
	}

	// Next we loop through the items one by one, processing them as we go, this
	// process is slightly recursive - LayoutItem may recurse to fill in any
	// 'holes' caused by glyphs not in the primary font.
	for(uint32_t i = 0; i < t_item_count && t_success; i++)
		t_success = MCTextLayoutStyleItem(
						self,
						t_items[i] . a,
						p_chars + t_items[i] . iCharPos,
						t_items[i + 1] . iCharPos - t_items[i] . iCharPos,
						self . primary_font);

	// At this point we should have an array of runs to render. First though we
	// need to compute the visual to logical mapping.
	uint8_t *t_levels;
	int *t_map;
	t_levels = nil;
	t_map = nil;
	if (t_success)
		t_success =
			MCMemoryNewArray(self . run_count, t_levels) &&
			MCMemoryNewArray(self . run_count, t_map);

	// Work out the run mapping, but only if we have runs to map!
	if (t_success && self . run_count > 0)
	{
		for(uint32_t i = 0; i < self . run_count; i++)
			t_levels[i] = self . runs[i] . embedding_level;

		if (ScriptLayout(self . run_count, t_levels, t_map, nil) != S_OK)
			t_success = false;
	}

	// Now we have the mapping we loop through the runs in the correct order
	// dispatching them to the callback.
	if (t_success && p_callback != nil)
	{
		double t_x;
		t_x = 0.0;
		for(uint32_t i = 0; i < self . run_count && t_success; i++)
		{
			MCTextLayoutRun *t_run;
			t_run = &self . runs[t_map[i]];

			// Allocate a temporary array for the glyph structures
			MCTextLayoutGlyph *t_glyphs;
			t_glyphs = nil;
			if (t_success)
				t_success = MCMemoryNewArray(t_run -> glyph_count, t_glyphs);

			if (t_success)
			{
				// Compute the position for each glyph, keeping a running
				// total of the advance width.
				for(uint32_t i = 0; i < t_run -> glyph_count; i++)
				{
					t_glyphs[i] . index = t_run -> glyphs[i];
					t_glyphs[i] . x = t_x + t_run -> goffsets[i] . du;
					t_glyphs[i] . y = t_run -> goffsets[i] . dv;
					t_x += t_run -> advances[i];
				}

				// Dispatch the span to the callback.
				MCTextLayoutSpan t_span;
				t_span . chars = t_run -> chars;
				t_span . clusters = t_run -> clusters;
				t_span . char_count = t_run -> char_count;
				t_span . glyphs = t_glyphs;
				t_span . glyph_count = t_run -> glyph_count;
				t_span . font = t_run -> font -> handle;
				t_success = p_callback(p_context, &t_span);
			}

			// Free the temporary array.
			MCMemoryDeleteArray(t_glyphs);
		}
	}

	// Free all the arrays and other resources that have been allocated.
	MCMemoryDeleteArray(t_map);
	MCMemoryDeleteArray(t_levels);

	for(uint32_t i = 0; i < self . run_count; i++)
	{
		MCMemoryDeallocate(self . runs[i] . chars);
		MCMemoryDeallocate(self . runs[i] . clusters);
		MCMemoryDeallocate(self . runs[i] . glyphs);
		MCMemoryDeallocate(self . runs[i] . advances);
		MCMemoryDeallocate(self . runs[i] . goffsets);
	}

	MCMemoryDeleteArray(self . runs);
	
	MCMemoryDeleteArray(t_items);

	if (self . dc != nil)
		DeleteDC(self . dc);

	return t_success;
}
Esempio n. 24
0
// SN-2014-09-01: [[ Bug 13297 ]] Combining by column deserves its own function as it is too
// different from combining by row
void MCArraysExecCombineByColumn(MCExecContext& ctxt, MCArrayRef p_array, MCStringRef &r_string)
{    
    MCStringRef t_row_delimiter, t_col_delimiter;
    t_row_delimiter = ctxt . GetRowDelimiter();
    t_col_delimiter = ctxt . GetColumnDelimiter();
    
    MCAutoListRef t_list;
    MCListCreateMutable(t_row_delimiter, &t_list);
    
    uindex_t t_count = MCArrayGetCount(p_array);
    combine_int_indexed_array_t t_lisctxt;
    bool t_success;
    
    t_lisctxt . elements = nil;
    t_lisctxt . index = 0;
    t_lisctxt . converter = &ctxt;
    t_success = MCMemoryNewArray(t_count, t_lisctxt . elements);
    
    if (t_success)
    {
        if (MCArrayApply(p_array, list_int_indexed_array_elements, &t_lisctxt))
        {
            bool t_valid_keys;
            
            qsort(t_lisctxt . elements, t_count, sizeof(array_element_t), compare_int_indexed_elements);
            
            // Combine by row/column is only valid if all the indices are consecutive numbers
            // Otherwise, an empty string is returned - no error
            index_t t_last_index;
            t_valid_keys = true;
            t_last_index = 0;
            for (int i = 0; i < t_count && t_valid_keys; ++i)
            {
                if (!t_last_index)
                    t_last_index = t_lisctxt . elements[i] . key;
                else
                    t_valid_keys = ++t_last_index == t_lisctxt . elements[i] . key;
            }
            
            if (t_valid_keys)
            {
                // SN-2014-09-01: [[ Bug 13297 ]]
                // We need to store the converted strings in a array, to be able to iterate through the elements by one row-delimitated
                //  at a time
                MCStringRef* t_strings;
                uindex_t *t_next_row_indices;
                
                t_strings = NULL;
                t_next_row_indices = NULL;
                
                /* UNCHECKED */ MCMemoryNewArray(t_count, t_strings);
                // MCMemoryNewArray initialises all t_next_row_indices elements to 0.
                /* UNCHECKED */ MCMemoryNewArray(t_count, t_next_row_indices);
                
                for (int i = 0; i < t_count && t_success; ++i)
                {
                    if (t_lisctxt . elements[i] . key == 0) // The index 0 is ignored
                        continue;
                    
                    t_success = ctxt . ConvertToString(t_lisctxt . elements[i] . value, t_strings[i]);
                }
                
                // SN-2014-09-01: [[ Bug 13297 ]] Added a missed part in column-combining:
                // only combining row-by-row the array elements.
                if (t_success)
                {
                    uindex_t t_elements_over;
                    t_elements_over = 0;
                    
                    // We iterate as long as one element still has uncombined rows
                    while (t_success && t_elements_over != t_count)
                    {
                        MCAutoListRef t_row;
                        
                        t_success = MCListCreateMutable(t_col_delimiter, &t_row);
                        t_elements_over = 0;
                        
                        // Iterate through all the elements of the array
                        for (int i = 0; i < t_count && t_success; ++i)
                        {
                            // Only consider this element if it has any uncombined rows remaining
                            if (t_next_row_indices[i] < MCStringGetLength(t_strings[i]))
                            {
                                MCRange t_cell_range;
                                if (MCStringFind(t_strings[i], MCRangeMake(t_next_row_indices[i], UINDEX_MAX), t_row_delimiter, ctxt.GetStringComparisonType(), &t_cell_range))
                                {
                                    // We found a row delimiter, so we stop the copy range before it and update the next index from which to look
                                    t_success = MCListAppendSubstring(*t_row, t_strings[i], MCRangeMake(t_next_row_indices[i], t_cell_range . offset - t_next_row_indices[i]));
                                    t_next_row_indices[i] = t_cell_range . offset + t_cell_range . length;
                                }
                                else
                                {
                                    // No row delimiter: we copy the remaining part of the string and mark the element
                                    // as wholly combined by setting the next index to the length of the element
                                    t_success = MCListAppendSubstring(*t_row, t_strings[i], MCRangeMake(t_next_row_indices[i], UINDEX_MAX));
                                    t_next_row_indices[i] = MCStringGetLength(t_strings[i]);
                                }
                            }
                            else
                            {
                                // Everything has been combined in this element
                                t_elements_over++;
                                MCListAppend(*t_row, kMCEmptyString);
                            }
                        }
                        
                        // One more row has been combined - doing it anyway mimics the previous behaviour of having an empty row
                        // added in the end when combining by columns
                        if (t_elements_over != t_count)
                            MCListAppend(*t_list, *t_row);
                    }
                }
                
                MCMemoryDeleteArray(t_next_row_indices);
                MCMemoryDeleteArray(t_strings);
            }
        }
        MCMemoryDeleteArray(t_lisctxt . elements);
    }
    
    if (t_success && MCListCopyAsString(*t_list, r_string))
        return;
    
    ctxt . Throw();
}
Esempio n. 25
0
static bool MCRegistryListValues(HKEY p_root, const char *p_key, MCRegistryListValuesCallback p_callback, void *p_context)
{
	bool t_success;
	t_success = true;

	// Attempt to open the given key.
	HKEY t_handle;
	t_handle = nil;
	if (t_success)
		if (RegOpenKeyExA(p_root, p_key, 0, KEY_QUERY_VALUE, &t_handle) != ERROR_SUCCESS)
			t_success = false;

	// Next determine the maximum length of the value names.
	DWORD t_max_name_length;
	if (t_success)
		if (RegQueryInfoKeyA(t_handle, nil, nil, nil, nil, nil, nil, nil, &t_max_name_length, nil, nil, nil) != ERROR_SUCCESS)
			t_success = false;

	// Allocate a buffer big enough for the name
	char *t_name_buffer;
	t_name_buffer = nil;
	if (t_success)
		t_success = MCMemoryNewArray(t_max_name_length + 1, t_name_buffer);

	if (t_success)
	{
		DWORD t_index;
		t_index = 0;
		while(t_success)
		{
			DWORD t_name_length, t_value_length;
			t_name_length = t_max_name_length + 1;
			t_value_length = 0;

			LSTATUS t_result;
			if (t_success)
			{
				t_result = RegEnumValueA(t_handle, t_index, t_name_buffer, &t_name_length, nil, nil, nil, &t_value_length);
				if (t_result == ERROR_NO_MORE_ITEMS)
					break;
				if (t_result != ERROR_SUCCESS)
					t_success = false;
			}

			void *t_value_buffer;
			t_value_buffer = nil;
			if (t_success)
				t_success = MCMemoryAllocate(t_value_length, t_value_buffer);

			DWORD t_type;
			if (t_success)
			{
				t_name_length = t_max_name_length + 1;
				if (RegEnumValueA(t_handle, t_index, t_name_buffer, &t_name_length, nil, &t_type, (LPBYTE)t_value_buffer, &t_value_length) != ERROR_SUCCESS)
					t_success = false;
			}

			if (t_success && p_callback != nil)
				p_callback(p_context, t_name_buffer, t_type, t_value_buffer, t_value_length);

			MCMemoryDeallocate(t_value_buffer);

			t_index++;
		}
	}

	MCMemoryDeleteArray(t_name_buffer);

	if (t_handle != nil)
		RegCloseKey(t_handle);

	return t_success;
}
Esempio n. 26
0
static int CALLBACK MCTextLayoutStyleItemCallback(HDC p_dc, HANDLETABLE *p_handles, const ENHMETARECORD *p_record, int p_object_count, LPARAM p_context)
{
	// This method assumes that the order of the TextOut records is in logical
	// order - i.e. no reversing for right-to-left text. This should be a valid
	// assumption to make since each SCRIPT_ITEM is rendered individually and
	// each such item is either all LTR or all RTL.
	
	// Additionally, it assumes that all printable chars (i.e. non-control) in
	// the analysed string will be part of some ExtTextOut record, even if the
	// suggested font (with linking) doesn't contain the characters.

	// Finally, it assumes that errant records which should not be rendered cause
	// a reference point advance of 0.

	MCTextLayoutStyleItemContext *context;
	context = (MCTextLayoutStyleItemContext *)p_context;

	bool t_success;
	t_success = true;

	bool t_flush;
	t_flush = false;

	int32_t t_new_pending_x;
	uint32_t t_new_pending_char_count;
	unichar_t *t_new_pending_chars;
	MCTextLayoutFont *t_new_pending_font;
	t_new_pending_x = 0;
	t_new_pending_char_count = 0;
	t_new_pending_chars = nil;
	t_new_pending_font = nil;

	switch(p_record -> iType)
	{
	case EMR_EXTCREATEFONTINDIRECTW:
		{
			EMREXTCREATEFONTINDIRECTW *t_record;
			t_record = (EMREXTCREATEFONTINDIRECTW *)p_record;

			// Attempt to create the font with the given info.
			p_handles -> objectHandle[t_record -> ihFont] = CreateFontIndirectW(&t_record -> elfw . elfLogFont);
			if (p_handles -> objectHandle[t_record -> ihFont] == nil)
				t_success = false;
		}
		break;
	case EMR_SELECTOBJECT:
		{
			EMRSELECTOBJECT *t_record;
			t_record = (EMRSELECTOBJECT *)p_record;

			// If the object being selected is a font, update our current font.
			if (GetObjectType(p_handles -> objectHandle[t_record -> ihObject]) == OBJ_FONT)
				t_success = MCTextLayoutFontFromHFONT((HFONT)p_handles -> objectHandle[t_record -> ihObject], context -> current_font);
		}
		break;
	case EMR_DELETEOBJECT:
		{
			EMRDELETEOBJECT *t_record;
			t_record = (EMRDELETEOBJECT *)p_record;

			// If the object being deleted is our current font, reset selection
			// to nil.
			if (p_handles -> objectHandle[t_record -> ihObject] == context -> current_font)
				context -> current_font = context -> primary_font;

			DeleteObject(p_handles -> objectHandle[t_record -> ihObject]);
			p_handles -> objectHandle[t_record -> ihObject] = nil;
		}
		break;
	case EMR_EXTTEXTOUTW:
		{
			EMREXTTEXTOUTW *t_record;
			t_record = (EMREXTTEXTOUTW *)p_record;

			unichar_t *t_run_chars;
			uint32_t t_run_char_count;
			t_run_chars = (unichar_t *)((char *)p_record + t_record -> emrtext . offString);
			t_run_char_count = t_record -> emrtext . nChars;

			if (t_run_char_count > 0)
			{
				if (MCMemoryNewArray(t_run_char_count, t_new_pending_chars))
				{
					t_flush = true;
					t_new_pending_x = t_record -> emrtext . ptlReference . x;
					t_new_pending_font = context -> current_font;
					t_new_pending_char_count = t_run_char_count;
					MCMemoryCopy(t_new_pending_chars, t_run_chars, t_new_pending_char_count * sizeof(uint16_t));
				}
				else
					t_success = false;
			}
		}
		break;
	case EMR_EOF:
		t_new_pending_x = MAXINT4;
		t_flush = true;
		break;
	}

	if (t_success && t_flush)
	{
		if (context -> pending_chars != nil && t_new_pending_x != context -> pending_x)
			t_success = MCTextLayoutLinkItem(*(context -> state), context -> analysis, context -> pending_chars, context -> pending_char_count, context -> pending_font);
		
		MCMemoryDeleteArray(context -> pending_chars);

		context -> pending_chars = t_new_pending_chars;
		context -> pending_char_count = t_new_pending_char_count;
		context -> pending_font = t_new_pending_font;
		context -> pending_x = t_new_pending_x;
	}

	if (!t_success)
		MCMemoryDeleteArray(context -> pending_chars);

	return t_success;
}
Esempio n. 27
0
static bool bsdiffmain(MCBsDiffInputStream *p_old_file, MCBsDiffInputStream *p_new_file, MCBsDiffOutputStream *p_patch_file)
{
	u_char *old,*newp;
	off_t oldsize,newsize;
	off_t *I,*V;
	off_t scan,pos,len;
	off_t lastscan,lastpos,lastoffset;
	off_t oldscore,scsc;
	off_t s,Sf,lenf,Sb,lenb;
	off_t overlap,Ss,lens;
	off_t i;
	off_t dblen,eblen;
	u_char *db,*eb;

	// if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
	bool t_success;
	t_success = true;
    
    V = NULL;

	/* Allocate oldsize+1 bytes instead of oldsize bytes to ensure
		that we never try to malloc(0) and get a NULL pointer */
	/*if(((fd=open(argv[1],O_RDONLY,0))<0) ||
		((oldsize=lseek(fd,0,SEEK_END))==-1) ||
		((old=malloc(oldsize+1))==NULL) ||
		(lseek(fd,0,SEEK_SET)!=0) ||
		(read(fd,old,oldsize)!=oldsize) ||
		(close(fd)==-1)) err(1,"%s",argv[1]);*/
	if (t_success)
	{
		uint32_t t_size;
		t_success = p_old_file -> Measure(t_size);
		oldsize = (signed)t_size;
	}
	if (t_success)
		t_success = MCMemoryNewArray(oldsize + 1, old);
	if (t_success)
		t_success = p_old_file -> ReadBytes(old, oldsize);
	
	/*if(((I=malloc((oldsize+1)*sizeof(off_t)))==NULL) ||
		((V=malloc((oldsize+1)*sizeof(off_t)))==NULL)) err(1,NULL);*/
	if (t_success)
		t_success = MCMemoryNewArray(oldsize + 1, I);
	if (t_success)
		t_success = MCMemoryNewArray(oldsize + 1, V);

    if (t_success)
        qsufsort(I,V,old,oldsize);

	/*free(V);*/
    MCMemoryDeleteArray(V);

	/* Allocate newsize+1 bytes instead of newsize bytes to ensure
		that we never try to malloc(0) and get a NULL pointer */
	/*if(((fd=open(argv[2],O_RDONLY,0))<0) ||
		((newsize=lseek(fd,0,SEEK_END))==-1) ||
		((newp=malloc(newsize+1))==NULL) ||
		(lseek(fd,0,SEEK_SET)!=0) ||
		(read(fd,newp,newsize)!=newsize) ||
		(close(fd)==-1)) err(1,"%s",argv[2]);*/
	if (t_success)
	{
		uint32_t t_size;
		t_success = p_new_file -> Measure(t_size);
		newsize = (signed)t_size;
	}
	if (t_success)
		t_success = MCMemoryNewArray(newsize + 1, newp);
	if (t_success)
		t_success = p_new_file -> ReadBytes(newp, newsize);

	/*if(((db=malloc(newsize+1))==NULL) ||
		((eb=malloc(newsize+1))==NULL)) err(1,NULL);*/
	if (t_success)
		t_success = MCMemoryNewArray(newsize + 1, db);
	if (t_success)
		t_success = MCMemoryNewArray(newsize + 1, eb);

	dblen=0;
	eblen=0;

	/* Create the patch file */
	/*if ((pf = fopen(argv[3], "w")) == NULL)
		err(1, "%s", argv[3]);*/

	/* Header is
		0	8	 "BSDIFF40"
		8	8	length of bzip2ed ctrl block
		16	8	length of bzip2ed diff block
		24	8	length of new file */
	/* File is
		0	32	Header
		32	??	Bzip2ed ctrl block
		??	??	Bzip2ed diff block
		??	??	Bzip2ed extra block */
	/*memcpy(header,"BSDIFF40",8);
	offtout(0, header + 8);
	offtout(0, header + 16);
	offtout(newsize, header + 24);
	if (fwrite(header, 32, 1, pf) != 1)
		err(1, "fwrite(%s)", argv[3]);*/
	uint32_t t_control_size, t_diff_size, t_extra_size;
	t_control_size = 0;
	t_diff_size = 0;
	t_extra_size = 0;
	if (t_success)
		t_success =
			p_patch_file -> WriteInt32(t_control_size) &&
			p_patch_file -> WriteInt32(t_diff_size) &&
			p_patch_file -> WriteInt32(t_extra_size) &&
			p_patch_file -> WriteInt32(newsize);

	/* Compute the differences, writing ctrl as we go */
	/*if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL)
		errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err);*/
	scan=0;len=0;
	lastscan=0;lastpos=0;lastoffset=0;
	while(t_success && scan<newsize) {
		oldscore=0;

		for(scsc=scan+=len;scan<newsize;scan++) {
			len=search(I,old,oldsize,newp+scan,newsize-scan,
					0,oldsize,&pos);

			for(;scsc<scan+len;scsc++)
			if((scsc+lastoffset<oldsize) &&
				(old[scsc+lastoffset] == newp[scsc]))
				oldscore++;

			if(((len==oldscore) && (len!=0)) || 
				(len>oldscore+8)) break;

			if((scan+lastoffset<oldsize) &&
				(old[scan+lastoffset] == newp[scan]))
				oldscore--;
		};

		if((len!=oldscore) || (scan==newsize)) {
			s=0;Sf=0;lenf=0;
			for(i=0;(lastscan+i<scan)&&(lastpos+i<oldsize);) {
				if(old[lastpos+i]==newp[lastscan+i]) s++;
				i++;
				if(s*2-i>Sf*2-lenf) { Sf=s; lenf=i; };
			};

			lenb=0;
			if(scan<newsize) {
				s=0;Sb=0;
				for(i=1;(scan>=lastscan+i)&&(pos>=i);i++) {
					if(old[pos-i]==newp[scan-i]) s++;
					if(s*2-i>Sb*2-lenb) { Sb=s; lenb=i; };
				};
			};

			if(lastscan+lenf>scan-lenb) {
				overlap=(lastscan+lenf)-(scan-lenb);
				s=0;Ss=0;lens=0;
				for(i=0;i<overlap;i++) {
					if(newp[lastscan+lenf-overlap+i]==
					   old[lastpos+lenf-overlap+i]) s++;
					if(newp[scan-lenb+i]==
					   old[pos-lenb+i]) s--;
					if(s>Ss) { Ss=s; lens=i+1; };
				};

				lenf+=lens-overlap;
				lenb-=lens;
			};

			for(i=0;i<lenf;i++)
				db[dblen+i]=newp[lastscan+i]-old[lastpos+i];
			for(i=0;i<(scan-lenb)-(lastscan+lenf);i++)
				eb[eblen+i]=newp[lastscan+lenf+i];

			dblen+=lenf;
			eblen+=(scan-lenb)-(lastscan+lenf);

			/*offtout(lenf,buf);
			BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
			if (bz2err != BZ_OK)
				errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);

			offtout((scan-lenb)-(lastscan+lenf),buf);
			BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
			if (bz2err != BZ_OK)
				errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);

			offtout((pos-lenb)-(lastpos+lenf),buf);
			BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
			if (bz2err != BZ_OK)
				errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);*/

			if (t_success)
				t_success =
					p_patch_file -> WriteInt32(lenf) &&
					p_patch_file -> WriteInt32((scan-lenb)-(lastscan+lenf)) &&
					p_patch_file -> WriteInt32((pos-lenb)-(lastpos+lenf));

			if (t_success)
				t_control_size += 12;

			lastscan=scan-lenb;
			lastpos=pos-lenb;
			lastoffset=pos-scan;
		};
	};
	/*BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL);
	if (bz2err != BZ_OK)
		errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err);*/

	/* Compute size of compressed ctrl data */
	/*if ((len = ftello(pf)) == -1)
		err(1, "ftello");
	offtout(len-32, header + 8);*/

	/* Write compressed diff data */
	/*if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL)
		errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err);
	BZ2_bzWrite(&bz2err, pfbz2, db, dblen);
	if (bz2err != BZ_OK)
		errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
	BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL);
	if (bz2err != BZ_OK)
		errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err);*/
	if (t_success)
		t_success = p_patch_file -> WriteBytes(db, dblen);
	if (t_success)
		t_diff_size = dblen;

	/* Compute size of compressed diff data */
	/*if ((newsize = ftello(pf)) == -1)
		err(1, "ftello");
	offtout(newsize - len, header + 16);*/

	/* Write compressed extra data */
	/*if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL)
		errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err);
	BZ2_bzWrite(&bz2err, pfbz2, eb, eblen);
	if (bz2err != BZ_OK)
		errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
	BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL);
	if (bz2err != BZ_OK)
		errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err);*/
	if (t_success)
		t_success = p_patch_file -> WriteBytes(eb, eblen);
	if (t_success)
		t_extra_size = eblen;

	/* Seek to the beginning, write the header, and close the file */
	/*if (fseeko(pf, 0, SEEK_SET))
		err(1, "fseeko");
	if (fwrite(header, 32, 1, pf) != 1)
		err(1, "fwrite(%s)", argv[3]);
	if (fclose(pf))
		err(1, "fclose");*/
	if (t_success)
		t_success =
			p_patch_file -> Rewind() &&
			p_patch_file -> WriteInt32(t_control_size) &&
			p_patch_file -> WriteInt32(t_diff_size) &&
			p_patch_file -> WriteInt32(t_extra_size) &&
			p_patch_file -> Rewind();

	/* Free the memory we used */
	/*free(db);
	free(eb);
	free(I);
	free(old);
	free(new);*/
	MCMemoryDeleteArray(db);
	MCMemoryDeleteArray(eb);
	MCMemoryDeleteArray(I);
	MCMemoryDeleteArray(old);
	MCMemoryDeleteArray(newp);

	return t_success;
}
Esempio n. 28
0
static bool MCTextLayoutLinkItem(MCTextLayoutState& self, SCRIPT_ANALYSIS p_analysis, const unichar_t *p_chars, uint32_t p_char_count, MCTextLayoutFont *p_font)
{
	bool t_success;
	t_success = true;

	// If the font is not linked, we can move directly to shaping
	if (p_font -> linking == nil)
		return MCTextLayoutShapeItem(self, p_analysis, p_chars, p_char_count, p_font, nil);

	// Otherwise we need to split up the run further into font ranges resulting
	// from font linking. Unfortunately, this is more complex than just looking
	// up each UTF-16 codepoint in the fonts support since we need to handle
	// combining cases and surrogates.

	// Make an array to hold cached text layout fonts, we get these as needed.
	MCTextLayoutFont **t_fonts;
	t_fonts = nil;
	if (t_success)
		t_success = MCMemoryNewArray(p_font -> linking -> entry_count + 1, t_fonts);

	// The first entry in the array is always the font we start with.
	if (t_success)
		t_fonts[0] = p_font;

	// We shape cluster by cluster, so determine the cluster boundaries using
	// ScriptBreak.
	SCRIPT_LOGATTR *t_breaks;
	t_breaks = nil;
	if (t_success)
		t_success = MCMemoryNewArray(p_char_count, t_breaks);

	if (t_success)
		if (ScriptBreak(p_chars, p_char_count, &p_analysis, t_breaks) != S_OK)
			t_success = false;

	// Now loop cluster by cluster, determining the font of each one. Note that
	// we can't use the results of shaping individual clusters to build up the
	// glyphs of the item since adjacent clusters may interact. For example, in
	// Sylfaen 'f' and 'i' and elide to form a proper 'fi' ligature.
	if (t_success)
	{
		MCTextLayoutFont *t_span_font;
		uint32_t t_span_start, t_span_finish;
		t_span_start = t_span_finish = 0;
		t_span_font = nil;
		while(t_success && t_span_finish < p_char_count)
		{
			// Compute bounds of next cluster
			uint32_t t_cluster_start, t_cluster_finish;
			t_cluster_start = t_span_finish;
			t_cluster_finish = t_cluster_start + 1;
			while(t_cluster_finish < p_char_count && !t_breaks[t_cluster_finish] . fCharStop)
				t_cluster_finish++;

			// Now try to shape the cluster in each font successively.
			MCTextLayoutFont *t_cluster_font;
			t_cluster_font = nil;
			for(uint32_t i = 0; i < p_font -> linking -> entry_count + 1 && t_success; i++)
			{
				// Get the font, if it doesn't already exist
				if (t_fonts[i] == nil)
					t_success = MCTextLayoutFontWithLink(p_font, &p_font -> linking -> entries[i - 1], t_fonts[i]);

				// Now try to shape the cluster with it
				bool t_shaped;
				if (t_success)
					t_success = MCTextLayoutShapeItem(self, p_analysis, p_chars + t_cluster_start, t_cluster_finish - t_cluster_start, t_fonts[i], &t_shaped);

				// If the shaping was successful we are done
				if (t_success && t_shaped)
				{
					t_cluster_font = t_fonts[i];
					break;
				}
			}

			// If the cluster's font is not the same as the span's font then we
			// have a run to shape.
			if (t_success && t_cluster_font != t_span_font)
			{
				if (t_span_start != t_span_finish)
					t_success = MCTextLayoutShapeItem(self, p_analysis, p_chars + t_span_start, t_span_finish - t_span_start, t_span_font, nil);

				// The next span starts where the previous one finishes and has
				// the font of the cluster we just shaped.
				if (t_success)
				{
					t_span_start = t_span_finish;
					t_span_font = t_cluster_font;
				}
			}
			
			// End of span is end of cluster
			t_span_finish = t_cluster_finish;
		}

		// Shape the trailing span
		if (t_success)
			t_success = MCTextLayoutShapeItem(self, p_analysis, p_chars + t_span_start, t_span_finish - t_span_start, t_span_font, nil);
	}

	MCMemoryDeleteArray(t_breaks);
	MCMemoryDeleteArray(t_fonts);

	return t_success;
}
Esempio n. 29
0
bool MCImageEncodePNG(MCImageIndexedBitmap *p_indexed, IO_handle p_stream, uindex_t &r_bytes_written)
{
	bool t_success = true;

	MCPNGWriteContext t_context;
	t_context.stream = p_stream;
	t_context.byte_count = 0;

	png_structp t_png_ptr = nil;
	png_infop t_info_ptr = nil;
	png_color *t_png_palette = nil;
	png_byte *t_png_transparency = nil;

	png_bytep t_data_ptr = nil;
	uindex_t t_stride = 0;

	/*init png stuff*/
	if (t_success)
	{
		t_success = nil != (t_png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
			(png_voidp)NULL, (png_error_ptr)NULL,
			(png_error_ptr)NULL));
	}

	if (t_success)
		t_success = nil != (t_info_ptr = png_create_info_struct(t_png_ptr));

	/*in case of png error*/
	if (setjmp(png_jmpbuf(t_png_ptr)))
		t_success = false;

	if (t_success)
		png_set_write_fn(t_png_ptr,(png_voidp)&t_context,fakewrite,fakeflush);

	if (t_success)
	{
		png_set_IHDR(t_png_ptr, t_info_ptr, p_indexed->width, p_indexed->height, 8,
					 PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
					 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
		png_set_gAMA(t_png_ptr, t_info_ptr, 1/MCgamma);
	}

	if (t_success)
		t_success = MCMemoryNewArray(p_indexed->palette_size, t_png_palette);

	/*create palette for 8 bit*/
	if (t_success)
	{
		for (uindex_t i = 0; i < p_indexed->palette_size ; i++)
		{
			t_png_palette[i].red   = p_indexed->palette[i].red >> 8;
			t_png_palette[i].green = p_indexed->palette[i].green >> 8;
			t_png_palette[i].blue  = p_indexed->palette[i].blue >> 8;
		}

		png_set_PLTE(t_png_ptr, t_info_ptr, t_png_palette, p_indexed->palette_size);
	}

	if (MCImageIndexedBitmapHasTransparency(p_indexed))
	{
		if (t_success)
			t_success = MCMemoryAllocate(p_indexed->palette_size, t_png_transparency);
		if (t_success)
		{
			memset(t_png_transparency, 0xFF, p_indexed->palette_size);
			t_png_transparency[p_indexed->transparent_index] = 0x00;
			png_set_tRNS(t_png_ptr, t_info_ptr, t_png_transparency, p_indexed->palette_size, NULL);
		}
	}
	if (t_success)
		png_write_info(t_png_ptr, t_info_ptr);

	if (t_success)
	{
		t_data_ptr = (png_bytep)p_indexed->data;
		t_stride = p_indexed->stride;
	}

	if (t_success)
	{
		for (uindex_t i = 0; i < p_indexed->height; i++)
		{
			png_write_row(t_png_ptr, t_data_ptr);
			t_data_ptr += t_stride;
		}
	}

	if (t_success)
		png_write_end(t_png_ptr, t_info_ptr);

	if (t_png_ptr != nil)
		png_destroy_write_struct(&t_png_ptr, &t_info_ptr);
	if (t_png_palette != nil)
		MCMemoryDeleteArray(t_png_palette);
	if (t_png_transparency != nil)
		MCMemoryDeallocate(t_png_transparency);

	if (t_success)
		r_bytes_written = t_context.byte_count;

	return t_success;
}
Esempio n. 30
0
bool MCTransformedImageRep::LoadImageFrames(MCImageFrame *&r_frames, uindex_t &r_frame_count)
{
	uindex_t t_target_width, t_target_height;
	if (!GetGeometry(t_target_width, t_target_height))
		return false;
	
	bool t_success = true;
	
	MCImageFrame *t_frames = nil;
	uindex_t t_frame_count = 0;
	
	t_frame_count = m_source->GetFrameCount();
	
	t_success = MCMemoryNewArray(t_frame_count, t_frames);
	
	for (uindex_t i = 0; t_success && i < t_frame_count; i++)
	{
		MCImageFrame *t_src_frame = nil;
		
		t_success = m_source->LockImageFrame(i, t_src_frame);
		if (t_success)
		{
			t_frames[i].duration = t_src_frame->duration;
			if (m_angle != 0)
			{
				// rotate
				MCImageBitmap *t_bitmap = nil;
				MCImageBitmap *t_rotated = nil;
				t_success = MCImageCopyBitmap(t_src_frame->image, t_bitmap);
				if (t_success)
				{
					MCImageBitmapPremultiply(t_bitmap);
					t_success = MCImageRotateBitmap(t_bitmap, m_angle, m_quality, 0x0, t_rotated);
				}
				
				MCImageFreeBitmap(t_bitmap);
				
				bool t_scaled = false;
				
				if (t_success && (t_rotated->width != t_target_width || t_rotated->height != t_target_height))
				{
					MCImageBitmap *t_sbitmap = nil;
					t_success = MCImageScaleBitmap(t_rotated, t_target_width, t_target_height, m_quality, t_sbitmap);
					MCImageFreeBitmap(t_rotated);
					t_rotated = t_sbitmap;
					t_scaled = true;
				}
				
				if (t_success)
				{
					if (t_scaled && (m_quality == INTERPOLATION_BICUBIC))
						MCImageBitmapUnpremultiplyChecking(t_rotated);
					else
						MCImageBitmapUnpremultiply(t_rotated);
					
					t_frames[i].image = t_rotated;
				}
				else
					MCImageFreeBitmap(t_rotated);
				
			}
			else
			{
				// resize
				if (t_src_frame->image->width == t_target_width && t_src_frame->image->height == t_target_height)
					t_success = MCImageCopyBitmap(t_src_frame->image, t_frames[i].image);
				else
					t_success = MCImageScaleBitmap(t_src_frame->image, t_target_width, t_target_height, m_quality, t_frames[i].image);
			}
		}
		m_source->UnlockImageFrame(i, t_src_frame);
	}
	
	if (t_success)
	{
		r_frames = t_frames;
		r_frame_count = t_frame_count;
	}
	else
		MCImageFreeFrames(t_frames, t_frame_count);
	
	return t_success;
}