/* $Header$ */

// OMNISICN.CPP
// External component OMNISICN
// Copyright (C) OMNIS Technology Inc 2000

/**************** Changes ******************
Date			Edit				Bug					Description
13-Jul-23 PK1597 			ST/FU/865 			using $getpict in a multi lib structure doesn't work
02-Mar-22	rmm11466								Implemented new build numbering and serial numbers to support Studio Now releases and periodic releases.
22-Jan-21	rmm_svg3								Support for themed fat client SVG icons.
14-Aug-20	rmm10594		ST/BE/1710	Omnisicn performance issue on Windows platform.
07-Apr-20	rmm_svg									Added support for SVG images.
05-Sep-19	rmm10138		ST/PF/1157	Crash on macOS - caused by using the EXTBMPref constructor that requires an HWND to be available.
24-Nov-16	CR0392			ST/FU/686		Allow $getpict/$getmask to turn off scaling of image when main display is hires.
12-Jan-09	rmm6556			ST/FU/554		Crash in OmnisIcn.$getpict() on OSX.
30-Jun-04	rmm5006									Multiple select knobs were missing from quite a few components.
22-Jun-04	rmm4999									Finished rmm4993: remote form fields now show $xxx correctly.
29-Dec-00	rmm3987			ST/EC/536		Problems drawing borders for transparent windows on Linux.
24-Mar-00	AE5031									Added $getpict to omnisicn
26-Jan-00	AE5003			ST/EC/409		Problems changing $transparent during design mode
*******************************************/

#include <extcomp.he>
#include <extfval.he>
#include <extbmp.he>
#include <hwnd.he>
#include <gdi.he>
#include "omnisicn.he"

#include <time.h>
#include <math.h>
#include <string.h>

#define COMPONENT_COUNT 	1				/* Number of controls within library */
#define LIB_RES_NAME  		1000		/* Resource id of library name */
#define OMNISICN_ID				2000		/* Resource id of control within library */
#define OMNISICN_ICON 		1				/* Resource bitmap id */

const qshort
				cOmnisIcnBackColor 				= 1,
				cOmnisIcnIsTransparent    = 2,
				cOmnisIcnIconId						= 3,
				cOmnisIcnScale						= 4;

ECOproperty OMNISICNproperties[] = // rmm_svg3
{ 
	anumTextColor,						0,			fftInteger,		EXTD_FLAG_PROPTEXT | EXTD_FLAG_PWINDCOL, 0, 0, 0, // rmm_svg3
	cOmnisIcnBackColor, 			4000, 	fftInteger, EXTD_FLAG_PWINDCOL, 0, 0, 0,										// backcolor
	cOmnisIcnIsTransparent, 	4001,		fftBoolean, 0, 0, 0, 0,																			// istransparent
	cOmnisIcnIconId, 					4002,		fftCharacter, EXTD_FLAG_PWINDICON, EXTD_EFLAG_SVG, 0, 0,		// iconid // rmm_svg
	cOmnisIcnScale, 					4003,		fftBoolean, 0, 0, 0, 0, 																		// scale
};
#define cOMNISICNpropCount (sizeof(OMNISICNproperties)/sizeof(OMNISICNproperties[0]))	// rmm_svg3

// Start rmm_svg3
ECOparam OMNISICNgetPictParams[] =
{
	8050, fftCharacter, 0, 0,											// cIconid
	8051,	fftInteger,		0, 0,											// iBackcolor
	8052, fftBoolean,		0, 0,											// bNoscale
	8053, fftInteger,		EXTD_FLAG_PARAMOPT, 0,		// iTextcolor
};
#define OMNISICNgetPictParamsCount (sizeof(OMNISICNgetPictParams)/sizeof(OMNISICNgetPictParams[0]))

ECOparam OMNISICNgetPictMaskParams[] =
{
	8050, fftCharacter, 0, 0,											// cIconid
	8052, fftBoolean,		0, 0,											// bNoscale
};
#define OMNISICNgetPictMaskParamsCount (sizeof(OMNISICNgetPictMaskParams)/sizeof(OMNISICNgetPictMaskParams[0]))
// End rmm_svg3
// AE5031 Starts
#define GetPictMthd		1
#define GetPictMaskMthd		2
ECOmethodEvent pictopsStaticFuncs[2] = 
{
	GetPictMthd				,8000,	fftPicture,	OMNISICNgetPictParamsCount, OMNISICNgetPictParams, 0, 0,						// rmm_svg3
	GetPictMaskMthd		,8001,	fftPicture,	OMNISICNgetPictMaskParamsCount, OMNISICNgetPictMaskParams, 0, 0			// rmm_svg3
};

qlong gPictMethod(EXTCompInfo* pEci)
{
	qlong funcId = ECOgetId(pEci);
	if (GetPictMthd == funcId || GetPictMaskMthd == funcId)
	{
		EXTParamInfo *param1 = ECOfindParamNum(pEci, 1);
		EXTParamInfo *param2 = ECOfindParamNum(pEci, 2);
		EXTParamInfo *param3 = ECOfindParamNum(pEci, 3);	// CR0392
		EXTParamInfo *param4 = ECOfindParamNum(pEci, 4);	// rmm_svg3
		if (param1) // rmm_svg3
		{
			EXTfldval iconid((qfldval)param1->mData); // rmm_svg
			qcol col = GDI_COLOR_WINDOW; // rmm_svg3
			qcol textColor = GDI_COLOR_WINDOWTEXT;	// rmm_svg3
			if (GetPictMthd == funcId)
			{
				if (param2) // rmm_svg3
				{
					EXTfldval p2((qfldval)param2->mData);
					col = (qcol)p2.getLong();
				}
				// Start rmm_svg3
				if (param4)
				{
					EXTfldval p4((qfldval)param4->mData);
					textColor = (qcol)p4.getLong();
				}
				// End rmm_svg3
			}
			
			EXTfldval result;

			//PK1597
			EXTBMPref* bmp = new EXTBMPref(iconid, ECOgetApp(pEci->mInstLocp));
			qbool retry = qfalse; if (!bmp) retry = qtrue;
			if ( bmp )
			{
				// check what we asked for is correct - as bmp could be deadref
				EXTfldval idx; bmp->getIconId(idx);
				retry = !EXTBMPref::iconIDsAreEqual(iconid,idx);
				if (retry) { delete bmp; bmp = NULL; }
				// if not what we asked for, try other locp
			}
			if (retry) bmp = new EXTBMPref(iconid, ECOgetApp(pEci->mLocLocp));
			if (bmp)
			{
				// Start CR0392
				qbool disableScaling = qfalse;
				GDIdeviceScale* scale = NULL;
				ECOdisableIconSetScaling* disableIconSetScaling = NULL;
				// End CR0392

				ePicSize psize = EXTBMPref::getBmpSize(iconid);
				qrect r; bmp->getRect(&r, psize);
				r.right -= r.left; r.left = 0;
				r.bottom -= r.top; r.top = 0;

				// Start CR0392
				if (GetPictMaskMthd == funcId && param2)
					param3 = param2;

				if (param3)
				{
					EXTfldval p3((qfldval)param3->mData);
					disableScaling = (qbool)(p3.getLong() != 0);
				}

				if (disableScaling)
				{
					scale = new GDIdeviceScale(1);
					disableIconSetScaling = new ECOdisableIconSetScaling();
				}
				// End CR0392

				HDC hdc = GDIgetTempDC();

				#ifdef ismacosx
					HBITMAP hbmp = GDIcreateBitmap(r.width(), r.height(), 0, hdc); // rmm6556
				#else
					HBITMAP hbmp = GDIcreateBitmap(r.width(), r.height(), 8, NULL);
				#endif
				HBITMAP old = GDIselectBitmap(hdc, hbmp);
				if (GetPictMthd == funcId)
					GDIsetTextColor(hdc, col);
				else
				{
					GDIsetTextColor(hdc, 0x00ffffffL);
					GDIsetBkColor(hdc, 0x00L);
				}
				GDIfillRect(hdc, &r, GDIgetStockBrush(BLACK_BRUSH));
				if (GetPictMthd == funcId)
				{
					GDIsetTextColor(hdc, textColor);	// rmm_svg3
					bmp->draw(hdc, &r, psize, picNormal, qfalse, colNone, qfalse, jstCenter, jstCenter);
				}
				else
				{
					bmp->drawMask(hdc, &r, psize, picNormal, qfalse, jstCenter, jstCenter);
					#if !defined(isunix) && !defined(ismac)
						GDIinvertRect(hdc, &r);
					#endif	
				}

				// Start CR0392
				if (scale) delete scale;
				if (disableIconSetScaling) delete disableIconSetScaling;
				// End CR0392

				GDIselectBitmap(hdc, old);
				GDIbitmapToColorShared(hbmp, result);
				delete bmp;
				GDIdeleteBitmap(hbmp);
			}
		  ECOaddParam(pEci, &result);
			return qtrue;
		}
	}
	return qfalse;
}
// AE5031 Ends               

// ---------------------------------------------------------------------------------------------------------

tqfOmnisIcn::tqfOmnisIcn( HWND pFieldHWnd )
{
	mApp = 0;	// rmm_svg
	mHWnd = pFieldHWnd;
	
	qlong style = WNDgetWindowLong( mHWnd, GWL_EXSTYLE );
	style |= WND_REDRAWONSIZE;
	WNDsetWindowLong( mHWnd, GWL_EXSTYLE, style );
	
	mBackColor = GDI_COLOR_3DFACE;
	mIsTransparent = mScale = qfalse;
	mIconId.setEmpty(fftInteger, 0);	// rmm_svg
	#ifdef isunix
		WNDsetWindowLong( mHWnd, GWL_NOCALCSIZE, qtrue); // rmm3987
	#endif
}

tqfOmnisIcn::~tqfOmnisIcn()
{
}

qlong tqfOmnisIcn::attributeSupport( LPARAM pMessage, WPARAM wParam, LPARAM lParam, EXTCompInfo* eci )
{
	switch( pMessage )
	{ 
		case ECM_PROPERTYCANASSIGN: 
		{
			return 1L;
		}
		case ECM_SETPROPERTY: 
		{       
			EXTParamInfo* param = ECOfindParamNum( eci, 1 );
			if ( param )
			{
				EXTfldval fval( (qfldval)param->mData );
				switch( ECOgetId(eci) )
				{
					case cOmnisIcnBackColor: 			mBackColor = (qcol)fval.getLong(); break; 			
					case cOmnisIcnIsTransparent: 	mIsTransparent = (qbool)fval.getLong(); break; 			
					case cOmnisIcnIconId: 				mIconId = fval; break;  // rmm_svg
					case cOmnisIcnScale:					mScale = (qbool)fval.getLong(); break; 			
				}       
				if ( ECOgetId(eci)==cOmnisIcnIsTransparent )
				{ 
					// check transparent window state
					// rmm10594: Removed change that made this a WND_LAYERED_CHILD on Windows
					qlong style = WNDgetWindowLong( mHWnd, GWL_EXSTYLE );
					qlong style1 = style & ~WND_TRANSPARENT;
					if ( mIsTransparent ) style1 |= WND_TRANSPARENT;  
					if ( style1!=style )
						WNDsetWindowLong( mHWnd, GWL_EXSTYLE, style1 );
				}
				doRedraw();	// rmm_svg3
				return 1L;
			}
			break;
		}
		case ECM_GETPROPERTY: 
		{
			EXTfldval fval;
			switch( ECOgetId(eci) )
			{
				case cOmnisIcnBackColor: 			fval.setLong( (qlong)mBackColor ); break; 			
				case cOmnisIcnIsTransparent: 	fval.setLong( (qlong)mIsTransparent ); break; 			
				case cOmnisIcnIconId: 				fval = mIconId; break;  // rmm_svg
				case cOmnisIcnScale:					fval.setLong( (qlong)mScale ); break; 	
			}         
			ECOaddParam(eci,&fval);
			return 1L;
		}
	}
	return 0;
}

// rmm_svg3: Made this a method
void tqfOmnisIcn::doRedraw()
{
	if (mIsTransparent)
	{
		HWND parent = WNDgetParent(mHWnd);
		if (parent)
		{
			qrect wRect; WNDgetWindowRect(mHWnd, &wRect);
			WNDmapWindowRect(HWND_DESKTOP, parent, &wRect);
			WNDredrawWindow(parent, &wRect, NULL, WND_RW_INVALIDATE | WND_RW_ALLCHILDREN | WND_RW_ERASE | WND_RW_NCPAINT); // AE5003 // rmm_svg3: erase and ncpaint
			WNDupdateWindow(parent);
		}
	}
	else
	{
		WNDinvalidateRect(mHWnd, NULL);
		WNDupdateWindow(mHWnd);
	}
	if (mIsTransparent)
		WNDredrawWindow(mHWnd, NULL, NULL, WND_RW_PAINT | WND_RW_NCPAINT); // AE5003
}

qbool tqfOmnisIcn::paint()
{
	// rmm3987: reworked a little, to allow border drawing in the client on Linux
	WNDpaintStruct paintStruct;
	WNDbeginPaint( mHWnd, &paintStruct );    
	#ifdef isunix
		qrect r; WNDgetClientRect(mHWnd, &r);
		WNDgetBorderSpec(mHWnd, &mBorder);
		WNDpaintBorder(mHWnd, paintStruct.hdc, &r, &mBorder);
	#endif
	if (EXTBMPref::isIconID(mIconId))	// rmm_svg
	{	
		EXTBMPref* bmp = new EXTBMPref(mIconId, mApp); // rmm_svg
		if ( bmp ) 
		{
			qrect r; WNDgetClientRect( mHWnd, &r );
			#ifdef isunix
				WNDinsetBorderRect(mHWnd, &r, &mBorder);
			#endif
			GDIsetTextColor(paintStruct.hdc, mTextColor);	// rmm_svg3
			bmp->draw(paintStruct.hdc, &r , EXTBMPref::getBmpSize( mIconId) , picNormal, qfalse, colNone, mScale, jstCenter, jstCenter);
			delete bmp;
		}
	}
	// Start rmm4999
	if (ECOisShowNumber(mHWnd))
		ECOdrawNumberEx(mHWnd, paintStruct.hdc, qtrue);
	// End rmm4999
	ECOdrawMultiKnobs(mHWnd, paintStruct.hdc);	// rmm5006
	WNDendPaint( mHWnd, &paintStruct );	
	return qtrue;
}


extern "C" LRESULT OMNISWNDPROC GenericWndProc( HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, EXTCompInfo* eci )
{
   ECOsetupCallbacks( hwnd, eci );
	 switch (Msg)
	 {
			case WM_ERASEBKGND:
			{
				tqfOmnisIcn* object = (tqfOmnisIcn*)ECOfindObject( eci, hwnd );
				if ( object )
				{
					if ( object->isTransparent() ) return 1L;
					HDC hdc = (HDC)wParam; qrect client;
					WNDgetClientRect( hwnd, &client );
					GDIsetTextColor( hdc, object->backColor() );
					GDIsetBkColor( hdc, object->backColor() );
					GDIfillRect( hdc,  &client, GDIgetStockBrush( BLACK_BRUSH) );
				}
				return 1L;
			}
			case WM_PAINT:							
			{
				tqfOmnisIcn* object = (tqfOmnisIcn*)ECOfindObject( eci, hwnd );
				if ( object && object->paint() )
					return qtrue;
				else if ( ECOisDesign (hwnd) )
				{
					return WNDdefWindowProc( hwnd, Msg, wParam, lParam, eci );
				}
				break;
			}
			case ECM_OBJCONSTRUCT:				/* Construct an object */
			{
				tqfOmnisIcn* object = new tqfOmnisIcn( hwnd );
				ECOinsertObject( eci, hwnd, (void*)object );
				object->mApp = ECOgetApp(eci->mInstLocp);	 // rmm_svg
				// Start rmm_svg3
				EXTfldval fval;
				ECOgetProperty(hwnd, anumTextColor, fval);
				object->mTextColor = (qcol)fval.getLong();
				// End rmm_svg3
				return qtrue;
			}
			case ECM_OBJDESTRUCT:					/* Destruct the object */
			{
				tqfOmnisIcn* object = (tqfOmnisIcn*)ECOremoveObject( eci, hwnd );
				if ( object ) delete object;              
				return qtrue;
			}
			case ECM_PROPERTYCANASSIGN:  	/* Object: Is the property assignable (ie readonly?) */
			case ECM_SETPROPERTY: 				/* Object: Assignment to a property */
			case ECM_GETPROPERTY:					/* Object: Retrieve value from property */
			{
				tqfOmnisIcn* object = (tqfOmnisIcn*)ECOfindObject( eci, hwnd );
				if ( object )
					return object->attributeSupport( Msg, wParam, lParam, eci );
				return 0L;
			}
			case WM_FLD_FONTCHANGED:  // rmm_svg3
			{
				tqfOmnisIcn* object = (tqfOmnisIcn*)ECOfindObject(eci, hwnd);
				if (object && object->mHWnd == hwnd)
				{
					object->mTextColor = ((GDItextSpecStruct*)lParam)->mTextColor;
					object->doRedraw();
				}
				break;
			}
      case ECM_GETCOMPLIBINFO:
      {
      	return ECOreturnCompInfo( gInstLib, eci, LIB_RES_NAME, COMPONENT_COUNT );
      }
			case ECM_GETCOMPICON:
			{ 	
				if ( eci->mCompId==OMNISICN_ID ) return ECOreturnIcon( gInstLib, eci, OMNISICN_ICON );
				return qfalse;
			}
			case ECM_GETCOMPID:
			{
				if ( wParam==1 )
					return ECOreturnCompID( gInstLib, eci, OMNISICN_ID, cObjType_Basic );
				return 0L;
			}
			case ECM_GETPROPNAME:
			{
				return ECOreturnProperties(gInstLib, eci, &OMNISICNproperties[0], cOMNISICNpropCount);	// rmm_svg3
			}
			// AE5031 Starts
	 		case ECM_CONNECT:
      {
        return ECOmakeConnectFlags(EXT_FLAG_LOADED|EXT_FLAG_ALWAYS_USABLE|EXT_FLAG_REMAINLOADED|EXT_FLAG_NVOBJECTS); // Return external flags // rmm11466
      } 
			case ECM_GETSTATICOBJECT:
			{
				return ECOreturnMethods( gInstLib, eci, &pictopsStaticFuncs[0], 2);
			}
			case ECM_METHODCALL:
			{
				return gPictMethod(eci);
			}
			// AE5031 Ends
		// Start rmm3987
		#ifdef isunix
			case WM_NCPAINT:
			{
				return TRUE;
			}
		#endif
		// End rmm3987
	 }
	 return WNDdefWindowProc(hwnd,Msg,wParam,lParam,eci);
}

	
