www.pudn.com > emGUI.rar > window.c


/* 
 *  Window layer 
 * 
 * 
 *  COPYRIGHT (c) 2001 - 2010. 
 *  emTech System Corporation. 
 * 
 *  The license and distribution terms for this file may be 
 *  found in found in the file LICENSE. 
 */ 
 
/*	Huangf emcore@263.net 
 */ 
  
#include "emGUI.h" 
 
#include  
#include  
 
void WndInitialization() 
{ 
} 
 
static void _SaveDrawArea( 
	Window *win 
) 
{ 
	void *memory 	= win->memory; 
	void *drawarea	= win->drawArea; 
 
	SaveDrawArea( 
		drawarea, 
		memory, 
		win->left, 
		win->top, 
		win->right, 
		win->bottom 
	); 
} 
 
static void _RestoreDrawArea( 
	Window *win 
) 
{ 
	void *memory 	= win->memory; 
	void *drawarea	= win->drawArea; 
 
	RestoreDrawArea( 
		drawarea, 
		memory, 
		win->left, 
		win->top, 
		win->right, 
		win->bottom 
	); 
} 
 
/*  API */ 
WndID CreateWindow( 
	AppID	app, 
	WndID	parent, 
	int 	mode, 
	void	*wndProc, 
	int		l, 
	int		t, 
	int		w, 
	int		h 
) 
{ 
	Window *win; 
 
	if (w <= 0 || h <= 0){ 
		return NULL; 
	} 
	 
	if (app == NULL){ 
		return NULL; 
	} 
 
	if (mode < 0 || mode > WINMODE_MAX){ 
		return NULL; 
	} 
 
	if (wndProc == NULL){ 
		return NULL; 
	} 
 
	win =(struct Window *) malloc(sizeof(struct Window)); 
	if (win == NULL) 
		return NULL; 
 
	memset(win, 0, sizeof(struct Window)); 
 
	/*  general information */	 
	win->application = app; 
	win->parent	 = parent; 
	win->mode 	 = mode; 
	win->wndProc = wndProc; 
	if (parent){ 
		/*  get absolute coord */ 
		win->left	 = l + parent->left; 
		win->top	 = t + parent->top; 
	} 
	else{ 
		win->left	 = l; 
		win->top	 = t; 
	} 
	win->right 	 = win->left + w - 1; 
	win->bottom  = win->top + h - 1; 
 
	/*  make win is inside screen or inside its parent */ 
	if (win->left < 0){ 
		win->left = 0; 
	} 
	if (win->top < 0){ 
		win->top = 0; 
	} 
 
	/*  Check right & bottom here */ 
	 
	/*  sun window list */ 
	_Chain_Initialize_empty( 
		&win->subWinList 
	); 
 
	/*  window drawing area */ 
	if (parent == NULL){ 
		switch(mode){ 
			case MAINWND: 
				win->memory 	= malloc(SysBytesPerScreen()); 
				win->drawArea	= win->memory; 
				break; 
				 
			case SYSMODAL: 
			case APPMODAL: 
				if (_Chain_Is_empty(&app->WinList)){ 
					/*  no MAINWIN defined before this window, 
					 *  not allowed in emGUI 
					 */ 
					free(win); 
					return NULL; 
				} 
				win->memory 	= malloc(CalcMemGCSize(win->left, win->top, w, h)); 
				win->drawArea	= ((Window *)(app->WinList.first))->drawArea; 
				_SaveDrawArea(win); 
				break; 
 
			if (win->memory == NULL){ 
				/*  have not Insert into */ 
				free(win); 
				return NULL; 
			} 
 
			default: 
				/* impossible */ 
				free(win); 
				return NULL; 
		} 
	} 
	else{ 
		win->mode		= SUBWIN; 
		win->memory 	= NULL; 
		win->drawArea	= parent->drawArea; 
	} 
 
		 
	if (parent == NULL){ 
		/*  insert into application window list */ 
		_Chain_Prepend_unprotected( 
			&app->WinList, 
			&win->node 
		); 
 
		/*  send a message to application */ 
		PostAppMessage( 
			app, 
			WNDCREATE, 
			0, 
			(unsigned32)win 
		); 
	} 
	else{ 
		/*  insert parent window list */ 
		_Chain_Prepend_unprotected( 
			&parent->subWinList, 
			&win->node 
		); 
	} 
 
	return win; 
} 
 
void DestroyWindow( 
	WndID	win 
) 
{ 
	if (win == NULL || win->application == NULL){ 
		return; 
	} 
	 
 	/*  Extract from window list, 
	 *  may from parent window's subWndList or Application's WindList 
	 */	 
	_Chain_Extract_unprotected( 
		&win->node 
	); 
	 
	if (win->mode == MAINWND){ 
		/*  send WNDCLOSE to Application, so it will switch draw base 
		 */ 
		PostAppMessage( 
			win->application, 
			WNDCLOSE, 
			0, 
			(unsigned32)win 
		); 
	} 
	else if (win->mode == SUBWIN){ 
		RECT rect = { 
			win->left - win->parent->left,  
			win->top - win->parent->top,  
			win->right - win->parent->left,  
			win->bottom - win->parent->top 
		}; 
		 
		InvalidateRect( 
			win->parent, 
			&rect 
		); 
	} 
	else{ 
		_RestoreDrawArea(win); 
	} 
	 
	/*  Post destroy message to current Window 
	 */ 
	PostMessage( 
		win, 
		WNDDESTROY, 
		0, 
		0L 
	); 
} 
 
/*  really destroy window, called by DefaultWndProc 
 */ 
void _DestroyWindow( 
	WndID	win 
) 
{ 
	if (win->memory){ 
		free(win->memory); 
	} 
	free(win); 
} 
 
Window *FindWindow( 
	Application *app, 
	int			x, 
	int			y 
) 
{ 
	Window *win, *subwin; 
	 
	/* 	find window in current application to handle this event, 
	 * 	rember, only the first window & its subwindows is searched 
	 */ 
	if (_Chain_Is_empty(&app->WinList)){ 
		return NULL; 
	} 
 
	win = (Window *)app->WinList.first; 
 
	while (win != (Window *)_Chain_Tail(&app->WinList)){ 
		if (win->left <= x && win->right >= x && win->top <= y && win->bottom >=y){ 
			goto findsubwin; 
		} 
		win = (Window *)win->node.next; 
	} 
	return NULL; 
 
findsubwin: 
	if (_Chain_Is_empty(&win->subWinList)){ 
		return win; 
	} 
 
	subwin = (Window *)win->subWinList.first; 
 
	while (subwin != (Window *)_Chain_Tail(&win->subWinList)){ 
		if (subwin->left <= x && subwin->right >= x && subwin->top <= y && subwin->bottom >=y){ 
			win = subwin; 
			goto findsubwin; 
		} 
		subwin = (Window *)subwin->node.next; 
	} 
 
	return win; 
} 
 
void HideWindow( 
	WndID	win 
) 
{ 
	RECT rect; 
	 
	if (win == NULL || win->application == NULL) 
		return; 
 
	/*  remove it from window list */ 
	_Chain_Extract_unprotected( 
		&win->node 
	); 
		 
	switch (win->mode){ 
		case MAINWND: 
			/*  switch drawing area 
			 */ 
			PostAppMessage( 
				win->application, 
				WM_HIDE, 
				0, 
				0L 
			); 
			break; 
 
		case SYSMODAL: 
		case APPMODAL: 
			/*  how to restore memory */ 
			_RestoreDrawArea(win); 
			break; 
 
		case SUBWIN: 
			rect.left	= win->left - win->parent->left; 
			rect.top	= win->top - win->parent->top; 
			rect.right	= win->right - win->parent->left; 
			rect.bottom = win->bottom - win->parent->top; 
			InvalidateRect( 
				win->parent, 
				&rect 
			); 
			break; 
	} 
} 
 
void ShowWindow( 
	WndID	win 
) 
{ 
	if (win == NULL || win->application == NULL) 
		return; 
	 
	if (win->parent){ 
		_Chain_Prepend_unprotected( 
			&win->parent->subWinList, 
			&win->node 
		); 
	} 
	else{ 
		_Chain_Prepend_unprotected( 
			&win->application->WinList, 
			&win->node 
		); 
	} 
 
	switch (win->mode){ 
		case MAINWND: 
			/*  switch drawing area 
			 */ 
			PostAppMessage( 
				win->application, 
				WM_SHOW, 
				0, 
				0L 
			); 
			break; 
 
		case SYSMODAL: 
		case APPMODAL: 
			/*  how to save memory */ 
			_SaveDrawArea(win); 
			 
		case SUBWIN: 
			/*  how to redraw window */ 
			win->invalid_l = 0; 
			win->invalid_t = 0; 
			win->invalid_r = win->right - win->left; 
			win->invalid_b = win->bottom - win->top; 
			win->paint_count++; 
			PostMessage( 
				win, 
				WM_PAINT, 
				0, 
				0L 
			); 
			break; 
	} 
} 
 
void InvalidateRect( 
	WndID	win, 
	LPRECT	lpRect 
) 
{ 
	lpRect->left 	+= win->left; 
	lpRect->top  	+= win->top; 
	lpRect->right 	+= win->left; 
	lpRect->bottom 	+= win->top; 
 
	if (win->invalid_l > lpRect->left){ 
		win->invalid_l = lpRect->left; 
	} 
	if (win->invalid_t > lpRect->top){ 
		win->invalid_t = lpRect->top; 
	} 
	if (win->invalid_b < lpRect->bottom){ 
		win->invalid_b = lpRect->bottom; 
	} 
	if (win->invalid_r < lpRect->right){ 
		win->invalid_r = lpRect->right; 
	} 
 
	/*  make invalidate rect is inside Window */ 
 
	win->paint_count++; 
	PostMessage( 
		win, 
		WM_PAINT, 
		0, 
		0L 
	); 
}