/*
 * Static control
 *
 * Copyright  David W. Metcalfe, 1993
 *
 */

static char Copyright[] = "Copyright  David W. Metcalfe, 1993";

#include <stdio.h>
#include <windows.h>
#include "win.h"
#include "user.h"

extern void DEFWND_SetText( HWND hwnd, LPSTR text );  /* windows/defwnd.c */

static LONG PaintTextfn(HWND hwnd);
static LONG PaintRectfn(HWND hwnd);
static LONG PaintFramefn(HWND hwnd);
static LONG PaintIconfn(HWND hwnd);


static COLORREF color_windowframe, color_background, color_window,
                                                     color_windowtext;

#define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \
	SendMessage(GetParent(hWndCntrl), WM_COMMAND, \
		    GetDlgCtrlID(hWndCntrl), MAKELPARAM(hWndCntrl, wNotifyCode));
#define DIM(array)	((sizeof array)/(sizeof array[0]))

typedef struct
{
    LONG (*paintfn)();
} STATICFN;

#define MAX_STATIC_TYPE  12

static STATICFN staticfn[MAX_STATIC_TYPE] =
{
    { (LONG(*)())PaintTextfn },                    /* SS_LEFT */
    { (LONG(*)())PaintTextfn },                    /* SS_CENTER */
    { (LONG(*)())PaintTextfn },                    /* SS_RIGHT */
    { (LONG(*)())PaintIconfn },                    /* SS_ICON */
    { (LONG(*)())PaintRectfn },                    /* SS_BLACKRECT */
    { (LONG(*)())PaintRectfn },                    /* SS_GRAYRECT */
    { (LONG(*)())PaintRectfn },                    /* SS_WHITERECT */
    { (LONG(*)())PaintFramefn },                   /* SS_BLACKFRAME */
    { (LONG(*)())PaintFramefn },                   /* SS_GRAYFRAME */
    { (LONG(*)())PaintFramefn },                   /* SS_WHITEFRAME */
    { (LONG(*)())PaintTextfn },                    /* SS_SIMPLE */
    { (LONG(*)())PaintTextfn }                     /* SS_LEFTNOWORDWRAP */
};


LONG StaticWndProc(HWND hWnd, WORD uMsg, WORD wParam, LONG lParam)
{
	LONG lResult = 0;
	HDC hDC;
	RECT rc;
	LPSTR textPtr;

	WND *wndPtr = WIN_FindWndPtr(hWnd);
	LONG style = wndPtr->dwStyle & 0x0000000F;

	switch (uMsg) {
	case WM_ENABLE:
	    InvalidateRect(hWnd, NULL, FALSE);
	    break;

	case WM_NCCREATE:
	    if (style == SS_ICON)
	    {
		  /* Note: we use wndPtr->hText to store the icon handle */
		CREATESTRUCT * createStruct = (CREATESTRUCT *)lParam;
		if (createStruct->lpszName)
		    wndPtr->hText = LoadIcon( createStruct->hInstance,
					      createStruct->lpszName );
		return 1;
	    }
	    else return DefWindowProc(hWnd, uMsg, wParam, lParam);

	case WM_NCDESTROY:
	    if (style == SS_ICON)
	    {
		if (wndPtr->hText) DestroyIcon( wndPtr->hText );
		wndPtr->hText = 0;
		return 0;
	    }
	    else return DefWindowProc(hWnd, uMsg, wParam, lParam);

	case WM_CREATE:
	    if (style < 0L || style >= (LONG)DIM(staticfn)) {
		lResult = -1L;
		break;
		}
	    /* initialise colours */
	    color_windowframe  = GetSysColor(COLOR_WINDOWFRAME);
	    color_background   = GetSysColor(COLOR_BACKGROUND);
	    color_window       = GetSysColor(COLOR_WINDOW);
	    color_windowtext   = GetSysColor(COLOR_WINDOWTEXT);
	    lResult = 0L;
	    if (style == SS_ICON) {
/*
		SetWindowPos(hWnd, (HWND)NULL, 0, 0, 32, 32,
				SWP_NOZORDER | SWP_NOMOVE);
*/
		}
	    break;

	case WM_PAINT:
	    if (staticfn[style].paintfn)
		(staticfn[style].paintfn)(hWnd);
	    break;

	case WM_SYSCOLORCHANGE:
	    color_windowframe  = GetSysColor(COLOR_WINDOWFRAME);
	    color_background   = GetSysColor(COLOR_BACKGROUND);
	    color_window       = GetSysColor(COLOR_WINDOW);
	    color_windowtext   = GetSysColor(COLOR_WINDOWTEXT);
	    InvalidateRect(hWnd, NULL, TRUE);
	    break;

	case WM_SETTEXT:
	    if (style == SS_ICON) break;
	    DEFWND_SetText( hWnd, (LPSTR)lParam );
	    InvalidateRect( hWnd, NULL, FALSE );
	    UpdateWindow( hWnd );
	    break;

	case WM_NCHITTEST:
	    return HTTRANSPARENT;

	case STM_GETICON:
	    if (style != SS_ICON) return 0;
	    return (HICON)wndPtr->hText;

	case STM_SETICON:
	    if (style != SS_ICON) return 0;
	    if (wndPtr->hText) DestroyIcon( wndPtr->hText );
	    wndPtr->hText = wParam;
	    InvalidateRect( hWnd, NULL, TRUE );
	    UpdateWindow( hWnd );
	    return 0;

	default:
		lResult = DefWindowProc(hWnd, uMsg, wParam, lParam);
		break;
	}

	return lResult;
}


static LONG PaintTextfn(HWND hwnd)
{
    PAINTSTRUCT ps;
    RECT rc;
    HDC hdc;
    HBRUSH hBrush;
    HANDLE hText;
    char *text;
    int textlen;
    WORD wFormat;

    WND *wndPtr = WIN_FindWndPtr(hwnd);
    LONG style = wndPtr->dwStyle;

    hdc = BeginPaint(hwnd, &ps);
    GetClientRect(hwnd, &rc);

    textlen = GetWindowTextLength(hwnd);
    hText = USER_HEAP_ALLOC(0, textlen+1);
    text = USER_HEAP_ADDR(hText);
    GetWindowText(hwnd, text, textlen+1);

    switch (style & 0x0000000F)
    {
    case SS_LEFT:
	wFormat = DT_LEFT | DT_EXPANDTABS | DT_WORDBREAK;
	break;

    case SS_CENTER:
	wFormat = DT_CENTER | DT_EXPANDTABS | DT_WORDBREAK;
	break;

    case SS_RIGHT:
	wFormat = DT_RIGHT | DT_EXPANDTABS | DT_WORDBREAK;
	break;

    case SS_SIMPLE:
	wFormat = DT_LEFT | DT_SINGLELINE | DT_VCENTER;
	break;

    case SS_LEFTNOWORDWRAP:
	wFormat = DT_LEFT | DT_SINGLELINE | DT_EXPANDTABS | DT_VCENTER;
	break;
    }

    if (style & SS_NOPREFIX)
	wFormat |= DT_NOPREFIX;

    hBrush = SendMessage(GetParent(hwnd), WM_CTLCOLOR, (WORD)hdc,
		    MAKELONG(hwnd, CTLCOLOR_STATIC));
    if (hBrush == (HBRUSH)NULL) hBrush = GetStockObject(WHITE_BRUSH);
    FillRect(hdc, &rc, hBrush);
    DrawText(hdc, text, textlen, &rc, wFormat);

    USER_HEAP_FREE(hText);
    EndPaint(hwnd, &ps);
}

static LONG PaintRectfn(HWND hwnd)
{
    PAINTSTRUCT ps;
    RECT rc;
    HDC hdc;
    HPEN hOldPen, hPen;
    HBRUSH hOldBrush, hBrush;

    WND *wndPtr = WIN_FindWndPtr(hwnd);

    hdc = BeginPaint(hwnd, &ps);
    GetClientRect(hwnd, &rc);
    
    switch (wndPtr->dwStyle & 0x0000000F)
    {
    case SS_BLACKRECT:
	hPen = CreatePen(PS_SOLID, 1, color_windowframe);
	hBrush = CreateSolidBrush(color_windowframe);
	break;

    case SS_GRAYRECT:
	hPen = CreatePen(PS_SOLID, 1, color_background);
	hBrush = CreateSolidBrush(color_background);
	break;

    case SS_WHITERECT:
	hPen = CreatePen(PS_SOLID, 1, color_window);
	hBrush = CreateSolidBrush(color_window);
	break;
    }

    hOldPen = (HPEN)SelectObject(hdc, (HANDLE)hPen);
    hOldBrush = (HBRUSH)SelectObject(hdc, (HANDLE)hBrush);
    Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);

    SelectObject(hdc, (HANDLE)hOldPen);
    SelectObject(hdc, (HANDLE)hOldBrush);
    DeleteObject((HANDLE)hPen);
    DeleteObject((HANDLE)hBrush);

    EndPaint(hwnd, &ps);
}

static LONG PaintFramefn(HWND hwnd)
{
    PAINTSTRUCT ps;
    RECT rc;
    HDC hdc;
    HPEN hOldPen, hPen;
    HBRUSH hOldBrush, hBrush;

    WND *wndPtr = WIN_FindWndPtr(hwnd);

    hdc = BeginPaint(hwnd, &ps);
    GetClientRect(hwnd, &rc);
    
    switch (wndPtr->dwStyle & 0x0000000F)
    {
    case SS_BLACKFRAME:
	hPen = CreatePen(PS_SOLID, 1, color_windowframe);
	break;

    case SS_GRAYFRAME:
	hPen = CreatePen(PS_SOLID, 1, color_background);
	break;

    case SS_WHITEFRAME:
	hPen = CreatePen(PS_SOLID, 1, color_window);
	break;
    }

    hBrush = CreateSolidBrush(color_window);
    hOldPen = (HPEN)SelectObject(hdc, (HANDLE)hPen);
    hOldBrush = (HBRUSH)SelectObject(hdc, (HANDLE)hBrush);
    Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);

    SelectObject(hdc, (HANDLE)hOldPen);
    SelectObject(hdc, (HANDLE)hOldBrush);
    DeleteObject((HANDLE)hPen);
    DeleteObject((HANDLE)hBrush);

    EndPaint(hwnd, &ps);
}


static LONG PaintIconfn(HWND hwnd)
{
    WND 	*wndPtr;
    PAINTSTRUCT ps;
    RECT 	rc;
    HDC 	hdc;

    wndPtr = WIN_FindWndPtr(hwnd);
    hdc = BeginPaint(hwnd, &ps);
    GetClientRect(hwnd, &rc);
    FillRect(hdc, &rc, GetStockObject(WHITE_BRUSH));
    if (wndPtr->hText) DrawIcon(hdc, rc.left, rc.top, wndPtr->hText );
    EndPaint(hwnd, &ps);
}
