/*******************************************************************/
/*                                                                 */
/*                      ADOBE CONFIDENTIAL                         */
/*                   _ _ _ _ _ _ _ _ _ _ _ _ _                     */
/*                                                                 */
/* Copyright 2000 Adobe Systems Incorporated                       */
/* All Rights Reserved.                                            */
/*                                                                 */
/* NOTICE:  All information contained herein is, and remains the   */
/* property of Adobe Systems Incorporated and its suppliers, if    */
/* any.  The intellectual and technical concepts contained         */
/* herein are proprietary to Adobe Systems Incorporated and its    */
/* suppliers and may be covered by U.S. and Foreign Patents,       */
/* patents in process, and are protected by trade secret or        */
/* copyright law.  Dissemination of this information or            */
/* reproduction of this material is strictly forbidden unless      */
/* prior written permission is obtained from Adobe Systems         */
/* Incorporated.                                                   */
/*                                                                 */
/*******************************************************************/
//-------------------------------------------------------------------
//-------------------------------------------------------------------------------
//
//	File:
//		PIUGet.cpp
//
//	Description:
//		Utility routines for getting information out of Photoshop
//
//	Version history:
//		Version 1.0.0	6/29/2000	Created for Photoshop 6.0.
//			Written by Thomas Ruark.
//
//-------------------------------------------------------------------------------
//-------------------------------------------------------------------------------
//	Includes
//-------------------------------------------------------------------------------
#include "PIUGet.h"



//-------------------------------------------------------------------------------
//
//	PIUGetInfo
//
// Given a class and an optional property PIUGetInfo will return the data you 
// requested in returnData. The returnExtraData will hold unit or string length 
// information and is optional.
//
//-------------------------------------------------------------------------------
SPErr PIUGetInfo(DescriptorClassID desiredClass, 
				 DescriptorKeyID desiredKey, 
				 void* returnData,
				 void* returnExtraData)
{
	SPErr error = kSPNoError;
    PIActionReference reference = NULL;
    PIActionDescriptor result = NULL;
	PIActionDescriptor* data;

	if (returnData == NULL)
		error = kSPBadParameterError;
	if (error) goto returnError;

	error = sPSActionReference->Make(&reference);
	if (error) goto returnError;

	if (desiredKey)
	{
		error = sPSActionReference->PutProperty(reference, 
			                                    classProperty, 
												desiredKey);
		if (error) goto returnError;
	}
	
	error = sPSActionReference->PutEnumerated(reference, 
											  desiredClass, 
											  typeOrdinal, 
											  enumTarget);
	if (error) goto returnError;
	
	error = sPSActionControl->Get(&result, reference);
	if (error) goto returnError;

	if (desiredKey)
	{
		error = PIUGetSingleItemFromDescriptor(result, 
											   desiredKey, 
											   returnData, 
											   returnExtraData);
		if (error) goto returnError;
	} else {
		data = (PIActionDescriptor*)returnData;
		*data = result;
		result = NULL; // you are responsible to free this guy
	}

returnError:
	
	if (reference) sPSActionReference->Free(reference);
	if (result)	sPSActionDescriptor->Free(result);
	
	return error;
}



//-------------------------------------------------------------------------------
//
//	PIUGetInfoByIndex
//
// This routine is like GetInfoFromPhotoshop but allows you to index into an 
// Object: Document, Layer, Channel, Path and get the information without having
// to select it first.
//
// NOTE:
// Some things like Paths have to be selected before you can actually get the
// information.
//-------------------------------------------------------------------------------
SPErr PIUGetInfoByIndex(uint32 index,
						DescriptorClassID desiredClass,
						DescriptorKeyID desiredKey,
						void* returnData,
						void* returnExtraData)
{
	SPErr error = kSPNoError;
    PIActionReference reference = NULL;
    PIActionDescriptor result = NULL;
	PIActionDescriptor* data;

	if (returnData == NULL)
		error = kSPBadParameterError;
	if (error) goto returnError;

	error = sPSActionReference->Make(&reference);
	if (error) goto returnError;
	
	if (desiredKey)
	{
		error = sPSActionReference->PutProperty(reference, 
												classProperty, 
												desiredKey);
		if (error) goto returnError;
	}
	
	error = sPSActionReference->PutIndex(reference, 
										 desiredClass, 
										 index);
	if (error) goto returnError;
	
	error = sPSActionControl->Get(&result, reference);
	if (error) goto returnError;

	if (desiredKey)
	{
		error = PIUGetSingleItemFromDescriptor(result, 
			                                   desiredKey, 
											   returnData, 
											   returnExtraData);
		if (error) goto returnError;
	} else {
		data = (PIActionDescriptor*)returnData;
		*data = result;
		result = NULL; // you are responsible to free this guy
	}

returnError:

	if (reference) sPSActionReference->Free(reference);
	if (result) sPSActionDescriptor->Free(result);
	
	return error;
}



//-------------------------------------------------------------------------------
//
//	PIUGetInfoByIndexIndex
//
// This routine is like GetInfoFromPhotoshop but allows you to index into an 
// Object: Document, Layer, Channel, Path and get the information without having 
// to select it first.
//
// NOTE:
// Some things like Paths have to be selected before you can actually get the
// information.
//-------------------------------------------------------------------------------
SPErr PIUGetInfoByIndexIndex(uint32 indexChild,
							 uint32 indexParent,
							 DescriptorClassID desiredClassChild,
							 DescriptorClassID desiredClassParent,
							 DescriptorKeyID desiredKey,
							 void* returnData,
							 void* returnExtraData)
{
	SPErr error = kSPNoError;
    PIActionReference reference = NULL;
    PIActionDescriptor result = NULL;
	PIActionDescriptor* data;

	if (returnData == NULL)
		error = kSPBadParameterError;
	if (error) goto returnError;

	error = sPSActionReference->Make(&reference);
	if (error) goto returnError;
	
	if (desiredKey)
	{
		error = sPSActionReference->PutProperty(reference, 
												classProperty, 
												desiredKey);
		if (error) goto returnError;
	}
	
	error = sPSActionReference->PutIndex(reference,
										 desiredClassChild,
										 indexChild);
	if (error) goto returnError;

	error = sPSActionReference->PutIndex(reference, 
										 desiredClassParent, 
										 indexParent);
	if (error) goto returnError;
	
	error = sPSActionControl->Get(&result, reference);
	if (error) goto returnError;

	if (desiredKey)
	{
		error = PIUGetSingleItemFromDescriptor(result, 
			                                   desiredKey, 
											   returnData, 
											   returnExtraData);
		if (error) goto returnError;
	} else {
		data = (PIActionDescriptor*)returnData;
		*data = result;
		result = NULL; // you are responsible to free this guy
	}

returnError:

	if (reference) sPSActionReference->Free(reference);
	if (result) sPSActionDescriptor->Free(result);
	
	return error;
}



//-------------------------------------------------------------------------------
//
//	PIUGetSingleItemFromDescriptor
//
// Pull a single thing out of a descriptor.
//-------------------------------------------------------------------------------
SPErr PIUGetSingleItemFromDescriptor(PIActionDescriptor result, 
								     DescriptorKeyID desiredKey, 
								     void* returnData,
								     void* returnExtraData)
{
	SPErr error = kSPNoError;
    Boolean hasKey = false;
    DescriptorEnumTypeID typeID;

	if (returnData == NULL)
		error = kSPBadParameterError;
	if (error) goto returnError;
    
    error = sPSActionDescriptor->HasKey(result, 
		                                desiredKey, 
										&hasKey);
	if (error) goto returnError;
        
    if (hasKey)
	{
		error = sPSActionDescriptor->GetType(result, 
			                                 desiredKey, 
											 &typeID);
		if (error) goto returnError;

		switch(typeID)
		{
			case typeInteger:
				error = sPSActionDescriptor->GetInteger(result, 
														desiredKey, 
														(int32*)returnData);
				break;
    
			case typeFloat:
				error = sPSActionDescriptor->GetFloat(result, 
													  desiredKey, 
													  (double*)returnData);
				break;
    
			case typeUnitFloat:
				if (returnExtraData == NULL)
					error = kSPBadParameterError;
				if (error) goto returnError;
				
				error = sPSActionDescriptor->GetUnitFloat(result, 
														  desiredKey, 
														  (DescriptorUnitID*)returnExtraData, 
														  (double*)returnData);
				break;
    
			case typeChar:
				if (returnExtraData == NULL)
					error = kSPBadParameterError;
				if (error) goto returnError;

				error = sPSActionDescriptor->GetStringLength(result, 
															 desiredKey, 
															 (uint32*)returnExtraData);
				if (error) goto returnError;
                
				error = sPSActionDescriptor->GetString(result, 
					                                   desiredKey, 
													   (char*)returnData, 
													   (*((int32*)returnExtraData))+1);
				break;
                
			case typeBoolean:
                error = sPSActionDescriptor->GetBoolean(result, 
					                                    desiredKey, 
														(Boolean*)returnData);
				break;
    
			case typeObject:
				if (returnExtraData == NULL)
					error = kSPBadParameterError;
				if (error) goto returnError;
                
				error = sPSActionDescriptor->GetObject(result, 
					                                   desiredKey, 
													   (DescriptorClassID*)returnExtraData, 
													   (PIActionDescriptor*)returnData);
				break;
    
			case typeGlobalObject:
				if (returnExtraData == NULL)
					error = kSPBadParameterError;
				if (error) goto returnError;
                
				error = sPSActionDescriptor->GetGlobalObject(result, 
															 desiredKey, 
															 (DescriptorClassID*)returnExtraData, 
															 (PIActionDescriptor*)returnData);
				break;
                    
			case typeEnumerated:
				if (returnExtraData == NULL)
					error = kSPBadParameterError;
				if (error) goto returnError;
                
				error = sPSActionDescriptor->GetEnumerated(result, 
														   desiredKey, 
														   (DescriptorEnumTypeID*)returnExtraData, 
														   (DescriptorEnumID*)returnData);
				break;
    
			case typePath:
			case typeAlias:
                error = sPSActionDescriptor->GetAlias(result, 
					                                  desiredKey, 
													  (Handle*)returnData);
				break;
    
			case typeValueList:
				error = sPSActionDescriptor->GetList(result, 
					                                 desiredKey, 
													 (PIActionList*)returnData);
				break;
    
			case typeObjectSpecifier:
                error = sPSActionDescriptor->GetReference(result, 
														  desiredKey, 
														  (PIActionReference*)returnData);
				break;
    
			case typeType:
			case typeGlobalClass:
                error = sPSActionDescriptor->GetClass(result, 
					                                  desiredKey, 
													  (DescriptorClassID*)returnData);
				break;
                    
			default:
				error = kSPUnimplementedError;
		}
	}
returnError:
	return error;
}



//-------------------------------------------------------------------------------
//
//	PIUGetErrorStringFromDescriptor
//
// Pulls an error string out of your descriptor, useful for debugging.
//-------------------------------------------------------------------------------
SPErr PIUGetErrorStringFromDescriptor(PIActionDescriptor descriptor,
								      char* stringPtr)
{
	SPErr error = kSPNoError;
    Boolean hasString = false;
	if (stringPtr)
	{
		error = kSPBadParameterError;
		goto returnError;
	}
	if (error) goto returnError;

	error = sPSActionDescriptor->HasKey(descriptor, 
											  keyMessage, 
											  &hasString);
    if (hasString && error == kSPNoError)
	{
		uint32 stringLength = 0;
		error = sPSActionDescriptor->GetStringLength(descriptor, 
			                                         keyMessage, 
													 &stringLength);
		if (stringLength && error == kSPNoError)
		{
			stringPtr = new char[stringLength+1];
			if (stringPtr)
				error = sPSActionDescriptor->GetString(descriptor, 
				                                       keyMessage, 
													   stringPtr, 
													   stringLength);
		}
	}
returnError:
	return (error);
}



//-------------------------------------------------------------------------------
//
//	PIUGetBackgroundInfo
//
//  Get information out of the background layer. The background layer is a layer
//	that isn't really a layer so you need this special get call.
//
//-------------------------------------------------------------------------------
SPErr PIUGetBackgroundInfo(DescriptorKeyID desiredKey, 
						   void* returnData,
						   void* returnExtraData)
{
	SPErr error = kSPNoError;
    PIActionReference reference = NULL;
    PIActionDescriptor result = NULL;
	PIActionDescriptor* data;

	if (returnData == NULL)
		error = kSPBadParameterError;
	if (error) goto returnError;

	error = sPSActionReference->Make(&reference);
	if (error) goto returnError;

	error = sPSActionReference->PutProperty(reference, 
 	                                        classBackgroundLayer, 
											keyBackground);
	if (error) goto returnError;
	
	error = sPSActionReference->PutEnumerated(reference, 
											  classDocument, 
											  typeOrdinal, 
											  enumTarget);
	if (error) goto returnError;
	
	error = sPSActionControl->Get(&result, reference);
	if (error) goto returnError;

	if (desiredKey)
	{
		error = PIUGetSingleItemFromDescriptor(result, 
											   desiredKey, 
											   returnData, 
											   returnExtraData);
		if (error) goto returnError;
	} else {
		data = (PIActionDescriptor*)returnData;
		*data = result;
		result = NULL; // you are responsible to free this guy
	}

returnError:
	
	if (reference) sPSActionReference->Free(reference);
	if (result)	sPSActionDescriptor->Free(result);
	
	return error;
}
// end PIUGet.cpp

