/*****************************************************
*
* Do_NewWindowFromAPI(outWindow) 
*
* Purpose:  called to create a new window using only API calls fron MacWindows.h, Controls.h, and HIView.h
*
* Notes:    called by Do_NewWindow()
*
* Inputs:   outWindow   - if not NULL, the address where to return the WindowRef
*                       - if not NULL, the callee will have to ShowWindow
*
* Returns:  OSStatus    - error code (0 == no error) 
*/
static OSStatus Do_NewWindowFromAPI(WindowRef * outWindow)
{
	WindowRef aWindowRef = NULL;
	CFStringRef theTitle = NULL;
	OSStatus status;
	
	// Create a window
	Rect bounds = {0, 0, 360, 480};
	status = CreateNewWindow(kDocumentWindowClass, kWindowStandardFloatingAttributes | kWindowStandardHandlerAttribute | kWindowCompositingAttribute | kWindowMetalAttribute, &bounds, &aWindowRef);
	require_noerr(status, CreateNewWindow);
	require(aWindowRef != NULL, CreateNewWindow);
	
	status = RepositionWindow(aWindowRef, NULL, kWindowCascadeOnMainScreen);
	require_noerr(status, RepositionWindow);
	
	HIViewRef contentView;
	status = HIViewFindByID(HIViewGetRoot(aWindowRef), kHIViewWindowContentID, &contentView);
	require_noerr(status, HIViewFindByID);
	
	ControlRef aControlRef;
	Rect statBounds = {113, 20, 177, 460};
	ControlFontStyleRec style = {kControlUseJustMask, 0, 0, 0, 0, teJustCenter};
	status = CreateStaticTextControl(NULL, &statBounds, CFSTR("Click in the LittleArrows control above."), &style, &aControlRef);
	require_noerr(status, CreateStaticTextControl);
	HIViewID staticTextID = { 'STTC', 100 };
	HIViewSetID(aControlRef, staticTextID);
	status = HIViewAddSubview(contentView, aControlRef);
	require_noerr(status, HIViewAddSubview);
	
	Rect littleArrowBounds = {51, 234, 73, 247};
	status = CreateLittleArrowsControl(NULL, &littleArrowBounds, 0, 0, 10, 1, &aControlRef);
	require_noerr(status, CreateLittleArrowsControl);
	status = HIViewAddSubview(contentView, aControlRef);
	require_noerr(status, HIViewAddSubview);

	SetControlAction(aControlRef, LittleArrowsControlAction);

	EventTypeSpec eventTypeCVFC = {kEventClassControl, kEventControlValueFieldChanged};
	status = HIViewInstallEventHandler(aControlRef, Handle_PostLittleArrowsClick, 1, &eventTypeCVFC, (void *)aControlRef, NULL);
	require_noerr(status, CantInstallEventHandler);

	Rect buttonBounds = {320, 390, 340, 460};
	status = CreatePushButtonControl(NULL, &buttonBounds, CFSTR("OK"), &aControlRef);
	require_noerr(status, CreatePushButtonControl);
	status = SetControlCommandID(aControlRef, kHICommandOK);
	require_noerr(status, SetControlCommandID);
	status = HIViewAddSubview(contentView, aControlRef);
	require_noerr(status, HIViewAddSubview);
	status = SetWindowDefaultButton(aWindowRef, aControlRef);
	require_noerr(status, SetWindowDefaultButton);
	
	WindowDataPtr wdr = (WindowDataPtr)calloc(1, sizeof(WindowDataRec));
	require(wdr != NULL, CantAllocateWindowData);

	SetWRefCon(aWindowRef, (long)wdr);
	
	theTitle = CFStringCreateWithFormat(NULL, NULL, CFSTR("LittleArrowsShowcase Window From API #%ld"), ++gWindowCount);
	require(theTitle != NULL, CFStringCreateWithFormat);
	
	status = SetWindowTitleWithCFString(aWindowRef, theTitle);
	require_noerr(status, SetWindowTitleWithCFString);
	
	EventTypeSpec eventTypeCP = {kEventClassCommand, kEventCommandProcess};
	status = InstallWindowEventHandler(aWindowRef, Handle_WindowCommandProcess, 1, &eventTypeCP, (void *)aWindowRef, NULL);
	require_noerr(status, CantInstallEventHandler);
	
	EventTypeSpec eventTypeWC = {kEventClassWindow, kEventWindowClosed};
	status = InstallWindowEventHandler(aWindowRef, Handle_WindowIsClosing, 1, &eventTypeWC, (void *)aWindowRef, NULL);
	require_noerr(status, CantInstallEventHandler);
		
	// The window was created hidden so show it if the outWindow parameter is NULL, 
	// if it's not, it will be the responsibility of the caller to show it.
	if (outWindow == NULL)
		ShowWindow(aWindowRef);
	
	SetWindowModified(aWindowRef, false);
	
CantInstallEventHandler:
SetWindowTitleWithCFString:
CFStringCreateWithFormat:

	if (theTitle != NULL)
		CFRelease(theTitle);

CantAllocateWindowData:
SetWindowDefaultButton:
SetControlCommandID:
CreatePushButtonControl:
CreateLittleArrowsControl:
HIViewAddSubview:
CreateStaticTextControl:
HIViewFindByID:
RepositionWindow:
CreateNewWindow:
	
	if (outWindow != NULL)
		*outWindow = aWindowRef;
	
	return status;
}   // Do_NewWindowFromAPI
OSStatus YASTControlAttachToExistingControl(ControlRef theControl) {
	OSStatus err;
	YASTControlVars *varsp;
	UInt32 outCommandID;
	EventHandlerRef controlEvents, windowEvents;
	TXNObject theTXNObject;
	RgnHandle outlineRegion;
	
		/* set up our locals */
	controlEvents = windowEvents = NULL;
	theTXNObject = NULL;
	outlineRegion = NULL;
	varsp = NULL;
	err = noErr;
	
		/* allocate our private storage and set up initial settings*/
	varsp = (YASTControlVars *) malloc(sizeof(YASTControlVars));
	if (varsp == NULL) {
		err = memFullErr;
	} else {
		varsp->fInFocus = false;
		varsp->fIsActive = true;
		varsp->fTXNObjectActive = false;
		varsp->fControl = theControl;
		varsp->fTabMovesFocus = true;
		varsp->fDrawFocusBox = true;
		varsp->fFocusDrawState = false;
		varsp->fIsReadOnly = false;
		varsp->fRTextOutlineRegion = NULL;
		varsp->fWindow = GetControlOwner(theControl);
		varsp->fGrafPtr = GetWindowPort(varsp->fWindow);
	}
	
		/* set our control's command id.  we don't actually use it, but it must
		be non-zero for our control to be sent command events.  only set it
		if it has not already been set.  */
	err = GetControlCommandID(theControl, &outCommandID);
	if (err == noErr) {
		if (outCommandID == 0) {
			err = SetControlCommandID(theControl, 1);
		}
	}
		/* calculate the rectangles used by the control */
	if (err == noErr) {
		outlineRegion = NewRgn();
		if (outlineRegion == NULL) {
			err = memFullErr;
		} else {
			Rect bounds;
			varsp->fRTextOutlineRegion = outlineRegion;
			GetControlBounds(theControl, &bounds);
			YASTControlCalculateBounds(varsp, &bounds);
		}
	}

		/* create the new edit field */
	if (err == noErr) {
		err = TXNNewObject(NULL, varsp->fWindow, &varsp->fRTextArea,
			kTXNWantVScrollBarMask | kTXNAlwaysWrapAtViewEdgeMask,
			kTXNTextEditStyleFrameType, kTXNTextensionFile, kTXNSystemDefaultEncoding, 
			&theTXNObject, &varsp->fTXNFrameID, (TXNObjectRefcon) varsp);
		if (err == noErr) {
			varsp->fTXNObject = theTXNObject;
		}
	}
	
		/* set the field's background */
	if (err == noErr) {
		RGBColor rgbWhite = {0xFFFF, 0xFFFF, 0xFFFF};
		TXNBackground tback;
		tback.bgType = kTXNBackgroundTypeRGB;
		tback.bg.color = rgbWhite;
		TXNSetBackground( varsp->fTXNObject, &tback);
	}
	
		/* set the margins for easier selection and display */
	if (err == noErr) {
		TXNControlData txnCControlData;
		TXNControlTag txnControlTag = kTXNMarginsTag;
		TXNMargins txnMargins = { 2, 3, 2, 1 };	/* t,l,b,r */
		txnCControlData.marginsPtr	= &txnMargins; 
		(void) TXNSetTXNObjectControls( varsp->fTXNObject, false, 1, &txnControlTag, &txnCControlData );
	}
	
		/* install our carbon event handlers */
	if (err == noErr) {
		static EventHandlerUPP gTPEventHandlerUPP = NULL;
		if (gTPEventHandlerUPP == NULL)
			gTPEventHandlerUPP = NewEventHandlerUPP(YASTControlCarbonEventHandler);
	
			/* carbon event handlers for the control */
		err = InstallEventHandler( GetControlEventTarget( theControl ),
			gTPEventHandlerUPP,
			(sizeof(gYASTControlEvents)/sizeof(EventTypeSpec)),
			gYASTControlEvents,
			varsp, &controlEvents);
		if (err == noErr) { 
			varsp->fControlEvents = windowEvents;
			
				/* carbon event handlers for the control's window */
			err = InstallEventHandler( GetWindowEventTarget( varsp->fWindow ),
				gTPEventHandlerUPP, (sizeof(gYASTControlWindowEvents)/sizeof(EventTypeSpec)),
				gYASTControlWindowEvents, varsp, &windowEvents);
			if (err == noErr) {
				varsp->fWindowEvents = windowEvents;
			}
		}
	}
	
		/* perform final activations and setup for our text field.  Here,
		we assume that the window is going to be the 'active' window. */
	if (err == noErr) {
		SetTextActivation(varsp, (varsp->fIsActive && varsp->fInFocus));
	}
	
		/* clean up on error */
	if (err != noErr) {
		if (controlEvents != NULL) RemoveEventHandler(controlEvents);
		if (windowEvents != NULL) RemoveEventHandler(windowEvents);
		if (theTXNObject != NULL) TXNDeleteObject(theTXNObject);
		if (outlineRegion != NULL) DisposeRgn(outlineRegion);
		if (varsp != NULL) free((void*) varsp);
	}
	
		/* all done */
	return err;
}